Get the FREE Ultimate OpenClaw Setup Guide →

Clean Code Patterns

Scanned
npx machina-cli add skill ruslan-korneev/python-backend-claude-plugins/clean-code-patterns --openclaw
Files (1)
SKILL.md
7.0 KB

Clean Code Patterns

Clean code principles for Python. Code should read like well-written prose.

Triggers

Use this skill when:

  • Code is hard to read or understand
  • Function/class does too much
  • Refactoring is needed
  • Code review revealed issues
  • Questions about SOLID, DRY, KISS

SOLID

More details: ${CLAUDE_PLUGIN_ROOT}/skills/clean-code-patterns/references/solid.md

S — Single Responsibility

# Bad — class does everything
class UserService:
    def create_user(self, data): ...
    def send_welcome_email(self, user): ...
    def generate_report(self, users): ...
    def export_to_csv(self, users): ...

# Good — each class = one responsibility
class UserService:
    def create_user(self, data): ...

class EmailService:
    def send_welcome_email(self, user): ...

class UserReportGenerator:
    def generate(self, users): ...
    def export_to_csv(self, users): ...

O — Open/Closed

# Bad — modify code when adding new type
def calculate_discount(order_type: str, amount: float) -> float:
    if order_type == "regular":
        return amount * 0.1
    elif order_type == "premium":
        return amount * 0.2
    elif order_type == "vip":  # Added new type — modified function
        return amount * 0.3

# Good — extend through new classes
from abc import ABC, abstractmethod

class DiscountStrategy(ABC):
    @abstractmethod
    def calculate(self, amount: float) -> float: ...

class RegularDiscount(DiscountStrategy):
    def calculate(self, amount: float) -> float:
        return amount * 0.1

class PremiumDiscount(DiscountStrategy):
    def calculate(self, amount: float) -> float:
        return amount * 0.2

# Add VIP — create new class, don't modify existing code
class VIPDiscount(DiscountStrategy):
    def calculate(self, amount: float) -> float:
        return amount * 0.3

L — Liskov Substitution

# Bad — subclass violates parent's contract
class Bird:
    def fly(self) -> None: ...

class Penguin(Bird):
    def fly(self) -> None:
        raise NotImplementedError("Penguins can't fly")  # LSP violation!

# Good — correct hierarchy
class Bird:
    def move(self) -> None: ...

class FlyingBird(Bird):
    def fly(self) -> None: ...

class Penguin(Bird):
    def move(self) -> None:
        self.swim()

I — Interface Segregation

# Bad — fat interface
class Worker(Protocol):
    def work(self) -> None: ...
    def eat(self) -> None: ...
    def sleep(self) -> None: ...

class Robot:  # Robot doesn't need eat and sleep!
    def work(self) -> None: ...
    def eat(self) -> None: raise NotImplementedError
    def sleep(self) -> None: raise NotImplementedError

# Good — small interfaces
class Workable(Protocol):
    def work(self) -> None: ...

class Eatable(Protocol):
    def eat(self) -> None: ...

class Robot:  # Implements only what's needed
    def work(self) -> None: ...

D — Dependency Inversion

# Bad — dependency on concrete implementation
class OrderService:
    def __init__(self):
        self.db = PostgresDatabase()  # Hard coupling!
        self.email = SendGridClient()  # Hard coupling!

# Good — dependency on abstractions
class OrderService:
    def __init__(
        self,
        db: DatabaseProtocol,
        email: EmailServiceProtocol,
    ):
        self.db = db
        self.email = email

DRY / KISS / YAGNI

More details: ${CLAUDE_PLUGIN_ROOT}/skills/clean-code-patterns/references/principles.md

DRY — Don't Repeat Yourself

# Bad — copy-paste
def create_admin(data):
    validate_email(data["email"])
    validate_password(data["password"])
    user = User(**data, role="admin")
    db.save(user)
    send_welcome_email(user)
    return user

def create_moderator(data):
    validate_email(data["email"])
    validate_password(data["password"])
    user = User(**data, role="moderator")
    db.save(user)
    send_welcome_email(user)
    return user

# Good — abstraction
def create_user(data: dict, role: str) -> User:
    validate_email(data["email"])
    validate_password(data["password"])
    user = User(**data, role=role)
    db.save(user)
    send_welcome_email(user)
    return user

KISS — Keep It Simple

# Bad — overengineering
class UserValidatorFactory:
    def create_validator(self, user_type: str) -> AbstractValidator:
        return self._validators[user_type]()

# Good — simple solution
def validate_user(user: User) -> bool:
    return user.email and user.name

YAGNI — You Aren't Gonna Need It

# Bad — features "for the future"
class User:
    name: str
    email: str
    phone: str | None  # "Might need it"
    fax: str | None    # "Just in case"
    secondary_email: str | None  # "Could be useful"

# Good — only what's needed now
class User:
    name: str
    email: str

Code Smells

More details: ${CLAUDE_PLUGIN_ROOT}/skills/clean-code-patterns/references/code-smells.md

Long Functions

# Bad — 100+ line function
def process_order(order):
    # validation (20 lines)
    # discount calculation (30 lines)
    # inventory update (25 lines)
    # notification sending (25 lines)
    ...

# Good — decomposition
def process_order(order: Order) -> ProcessedOrder:
    validated = validate_order(order)
    with_discount = apply_discounts(validated)
    update_inventory(with_discount)
    notify_customer(with_discount)
    return with_discount

Too Many Parameters

# Bad — too many parameters
def create_user(name, email, age, city, country, phone, role, department): ...

# Good — Parameter Object
@dataclass
class CreateUserRequest:
    name: str
    email: str
    age: int
    city: str
    country: str
    phone: str
    role: str
    department: str

def create_user(request: CreateUserRequest): ...

Nested Conditionals

# Bad — deep nesting
def process(user):
    if user:
        if user.is_active:
            if user.has_permission:
                if user.balance > 0:
                    return do_something(user)
    return None

# Good — guard clauses (early return)
def process(user):
    if not user:
        return None
    if not user.is_active:
        return None
    if not user.has_permission:
        return None
    if user.balance <= 0:
        return None
    return do_something(user)

Naming

More details: ${CLAUDE_PLUGIN_ROOT}/skills/clean-code-patterns/references/naming.md

Variables

# Bad
d = 86400
u = get_user()
tmp = calculate()

# Good
SECONDS_IN_DAY = 86400
current_user = get_user()
total_price = calculate()

Boolean Variables

# Bad
flag = True
status = False
check = user.admin

# Good
is_active = True
has_permission = False
is_admin = user.admin

Functions

# Bad — unclear what it does
def process(data): ...
def handle(x): ...
def do_stuff(): ...

# Good — verb + noun
def calculate_total_price(items): ...
def send_welcome_email(user): ...
def validate_order_items(order): ...

Plugin Commands

  • /clean:review — analyze code for code smells
  • /clean:refactor <smell> — suggest refactoring

Source

git clone https://github.com/ruslan-korneev/python-backend-claude-plugins/blob/master/plugins/python/skills/clean-code-patterns/SKILL.mdView on GitHub

Overview

Clean Code Patterns teaches Python-friendly guidelines to write readable, maintainable code. It covers SOLID, DRY, KISS, and practical patterns that reduce complexity and clarify intent. Use it when code is hard to read, a function or class does too much, or refactoring is needed.

How This Skill Works

The skill provides concrete bad-vs-good examples across SOLID, DRY, and interface design, then demonstrates refactors that decouple responsibilities and introduce abstractions. It emphasizes using small, well-defined interfaces, dependency inversion, and pattern-based strategies to extend behavior without modifying existing code. It relies on Python code sketches to show practical improvements.

When to Use It

  • Code is hard to read or understand
  • Function or class does too much (violates SRP)
  • Refactoring is needed
  • Code review revealed issues
  • Questions about SOLID, DRY, KISS, and YAGNI

Quick Start

  1. Step 1: Identify SRP violations and extract responsibilities into separate classes.
  2. Step 2: Introduce small interfaces and DI, refactor to use them.
  3. Step 3: Replace hard-coded logic with strategy-based extensible patterns and run tests.

Best Practices

  • Separate concerns with Single Responsibility Principle (SRP) by assigning one reason to change to each class or module
  • Prefer open/closed via strategy/abstraction; add new behavior without modifying existing code
  • Use small interfaces and interface segregation; implement only what is needed
  • Inject dependencies via abstractions (DI) instead of hard coupling to concrete implementations
  • DRY and KISS: factor out common operations, avoid duplication, and keep code readable

Example Use Cases

  • Split a bloated UserService into UserService, EmailService, and UserReportGenerator.
  • Replace a big if/elif in discounts with a DiscountStrategy family (RegularDiscount, PremiumDiscount, VIPDiscount).
  • Refactor a Bird/Penguin example to satisfy LSP by moving behavior into proper hierarchies.
  • Create focused interfaces Workable and Eatable to avoid fat protocols.
  • Inject dependencies (db, email) through abstractions to decouple OrderService from concrete implementations.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers