Skip to content
Back to skills

2557 Smell Patterns 372f30a8

ASecurity

Comprehensive catalog of code quality and design smells in Python.

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 31, 2026
code-qualitypythongorefactoringsecurity

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 31, 2026

npx -y skills add tools-only/X-Skills --skill 2557-smell-patterns_372f30a8 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2557 Smell Patterns 372f30a8?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2557 Smell Patterns 372f30a8
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2557-smell-patterns-372f30a8/badge)](https://www.skillsdirectory.com/skills/tools-only-2557-smell-patterns-372f30a8)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Code Smell Patterns Reference

Comprehensive catalog of code quality and design smells in Python.

## Code Quality Smells

### Pattern 1: Duplicate Code

**Description:** Same or very similar code appears in multiple places.

**Impact:** Changes must be made in multiple locations, increasing maintenance burden and bug risk.

**Detection:**
- Identical or nearly identical code blocks
- Copy-pasted functions with minor variations
- Similar logic in multiple methods

**Example:**
```python
# ❌ Duplicate code
class UserService:
    def create_user(self, data):
        if not data.get('email'):
            raise ValueError("Email required")
        if not data.get('name'):
            raise ValueError("Name required")
        # Create user...

    def update_user(self, data):
        if not data.get('email'):
            raise ValueError("Email required")
        if not data.get('name'):
            raise ValueError("Name required")
        # Update user...

# ✅ Extract common validation
class UserService:
    def _validate_user_data(self, data):
        if not data.get('email'):
            raise ValueError("Email required")
        if not data.get('name'):
            raise ValueError("Name required")

    def create_user(self, data):
        self._validate_user_data(data)
        # Create user...

    def update_user(self, data):
        self._validate_user_data(data)
        # Update user...
```

**Refactoring:** Extract Method, Pull Up Method, Form Template Method

### Pattern 2: Magic Numbers

**Description:** Numeric literals with unclear meaning appearing directly in code.

**Impact:** Hard to understand intent, difficult to change, easy to make mistakes.

**Example:**
```python
# ❌ Magic numbers
def calculate_discount(price):
    if price > 1000:
        return price * 0.15
    elif price > 500:
        return price * 0.10
    else:
        return price * 0.05

# ✅ Named constants
BULK_ORDER_THRESHOLD = 1000
LARGE_ORDER_THRESHOLD = 500
BULK_DISCOUNT_RATE = 0.15
LARGE_DISCOUNT_RATE = 0.10
STANDARD_DISCOUNT_RATE = 0.05

def calculate_discount(price):
    if price > BULK_ORDER_THRESHOLD:
        return price * BULK_DISCOUNT_RATE
    elif price > LARGE_ORDER_THRESHOLD:
        return price * LARGE_DISCOUNT_RATE
    else:
        return price * STANDARD_DISCOUNT_RATE
```

**Refactoring:** Replace Magic Number with Symbolic Constant

### Pattern 3: Hardcoded Values

**Description:** Configuration values, paths, or strings embedded directly in code.

**Impact:** Difficult to change for different environments, violates DRY principle.

**Example:**
```python
# ❌ Hardcoded values
def save_file(data):
    with open('/var/app/data/output.txt', 'w') as f:
        f.write(data)

def send_email(user):
    send_to('admin@example.com', f'User {user.name} registered')

# ✅ Configuration-based
import os

class Config:
    OUTPUT_PATH = os.getenv('OUTPUT_PATH', '/var/app/data/output.txt')
    ADMIN_EMAIL = os.getenv('ADMIN_EMAIL', 'admin@example.com')

def save_file(data):
    with open(Config.OUTPUT_PATH, 'w') as f:
        f.write(data)

def send_email(user):
    send_to(Config.ADMIN_EMAIL, f'User {user.name} registered')
```

**Refactoring:** Introduce Parameter Object, Use Configuration

### Pattern 4: Commented-Out Code

**Description:** Code that has been commented out but not removed.

**Impact:** Clutters codebase, creates confusion about what's actually used.

**Example:**
```python
# ❌ Commented code
def process_order(order):
    # Old implementation
    # validate_order(order)
    # calculate_total(order)
    # charge_payment(order)

    # New implementation
    process_payment_v2(order)
    send_confirmation(order)

# ✅ Clean code
def process_order(order):
    process_payment(order)
    send_confirmation(order)
```

**Refactoring:** Delete the code (version control preserves history)

### Pattern 5: Long Identifier Names

**Description:** Excessively long variable or function names.

**Impact:** Reduces readability, makes code harder to scan.

**Example:**
```python
# ❌ Too long
def calculate_total_price_including_tax_and_shipping_for_customer_order(order):
    pass

# ✅ Appropriately named
def calculate_order_total(order):
    """Calculate total including tax and shipping."""
    pass
```

**Refactoring:** Rename, use docstrings for detailed explanations

### Pattern 6: Inconsistent Naming

**Description:** Similar concepts use different naming conventions.

**Impact:** Confusing, harder to learn codebase.

**Example:**
```python
# ❌ Inconsistent
def getUserData(user_id):
    pass

def fetch_product_info(product_id):
    pass

def RetrieveOrderDetails(order_id):
    pass

# ✅ Consistent
def get_user(user_id):
    pass

def get_product(product_id):
    pass

def get_order(order_id):
    pass
```

**Refactoring:** Standardize naming conventions

## Design Smells

### Pattern 7: God Class

**Description:** Class that knows too much or does too much.

**Impact:** Hard to understand, test, and maintain. Violates Single Responsibility Principle.

**Indicators:**
- More than 20 methods
- Touches many different concerns
- Large number of fields
- Many dependencies

**Example:**
```python
# ❌ God class
class UserManager:
    def create_user(self, data): pass
    def update_user(self, user_id, data): pass
    def delete_user(self, user_id): pass
    def authenticate_user(self, username, password): pass
    def send_welcome_email(self, user): pass
    def send_password_reset_email(self, user): pass
    def generate_password_reset_token(self, user): pass
    def validate_password_strength(self, password): pass
    def hash_password(self, password): pass
    def log_user_activity(self, user, action): pass
    def export_user_data(self, user): pass
    def import_user_data(self, data): pass
    def calculate_user_statistics(self, user): pass
    def get_user_recommendations(self, user): pass
    # ... 20+ more methods

# ✅ Split by responsibility
class UserRepository:
    def create(self, data): pass
    def update(self, user_id, data): pass
    def delete(self, user_id): pass
    def find_by_id(self, user_id): pass

class UserAuthenticationService:
    def authenticate(self, username, password): pass
    def hash_password(self, password): pass
    def validate_password_strength(self, password): pass
    def generate_reset_token(self, user): pass

class UserNotificationService:
    def send_welcome_email(self, user): pass
    def send_password_reset_email(self, user): pass

class UserAnalyticsService:
    def log_activity(self, user, action): pass
    def calculate_statistics(self, user): pass
    def get_recommendations(self, user): pass
```

**Refactoring:** Extract Class, Extract Service

### Pattern 8: Feature Envy

**Description:** Method uses more features from another class than its own.

**Impact:** Poor cohesion, method is in the wrong place.

**Example:**
```python
# ❌ Feature envy
class Order:
    def __init__(self, items, customer):
        self.items = items
        self.customer = customer

    def calculate_total(self):
        # Uses customer features heavily
        discount_rate = self.customer.get_discount_rate()
        is_premium = self.customer.is_premium_member()
        shipping_address = self.customer.get_shipping_address()

        total = sum(item.price for item in self.items)

        if is_premium:
            total *= (1 - discount_rate)

        if shipping_address.country != 'US':
            total += 50  # International shipping

        return total

# ✅ Move method to appropriate class
class Customer:
    def calculate_order_total(self, items):
        total = sum(item.price for item in items)

        if self.is_premium_member():
            total *= (1 - self.get_discount_rate())

        if self.shipping_address.country != 'US':
            total += 50

        return total

class Order:
    def __init__(self, items, customer):
        self.items = items
        self.customer = customer

    def calculate_total(self):
        return self.customer.calculate_order_total(self.items)
```

**Refactoring:** Move Method, Extract Method

### Pattern 9: Inappropriate Intimacy

**Description:** Classes that access each other's internal details too much.

**Impact:** Tight coupling, changes ripple across classes.

**Example:**
```python
# ❌ Inappropriate intimacy
class BankAccount:
    def __init__(self):
        self.balance = 0
        self._transaction_log = []

class AccountManager:
    def transfer_funds(self, from_account, to_account, amount):
        # Directly accessing internals
        if from_account.balance >= amount:
            from_account.balance -= amount
            to_account.balance += amount
            from_account._transaction_log.append(f"Transferred {amount}")
            to_account._transaction_log.append(f"Received {amount}")

# ✅ Use proper encapsulation
class BankAccount:
    def __init__(self):
        self._balance = 0
        self._transaction_log = []

    def withdraw(self, amount):
        if self._balance >= amount:
            self._balance -= amount
            self._log_transaction(f"Withdrew {amount}")
            return True
        return False

    def deposit(self, amount):
        self._balance += amount
        self._log_transaction(f"Deposited {amount}")

    def _log_transaction(self, message):
        self._transaction_log.append(message)

class AccountManager:
    def transfer_funds(self, from_account, to_account, amount):
        if from_account.withdraw(amount):
            to_account.deposit(amount)
            return True
        return False
```

**Refactoring:** Move Method, Hide Delegate, Encapsulate Field

### Pattern 10: Data Clumps

**Description:** Same group of variables appears together in multiple places.

**Impact:** Suggests missing abstraction, code duplication.

**Example:**
```python
# ❌ Data clumps
def create_user(name, email, phone, address_street, address_city, address_zip):
    pass

def update_user(user_id, name, email, phone, address_street, address_city, address_zip):
    pass

def send_mail(name, email, phone, address_street, address_city, address_zip):
    pass

# ✅ Introduce parameter object
from dataclasses import dataclass

@dataclass
class Address:
    street: str
    city: str
    zip_code: str

@dataclass
class ContactInfo:
    name: str
    email: str
    phone: str
    address: Address

def create_user(contact_info: ContactInfo):
    pass

def update_user(user_id: int, contact_info: ContactInfo):
    pass

def send_mail(contact_info: ContactInfo):
    pass
```

**Refactoring:** Extract Class, Introduce Parameter Object

### Pattern 11: Primitive Obsession

**Description:** Using primitive types instead of small objects for simple tasks.

**Impact:** Missing domain concepts, validation logic scattered.

**Example:**
```python
# ❌ Primitive obsession
def process_order(order_id: str, customer_email: str, total_cents: int):
    # Validation scattered
    if '@' not in customer_email:
        raise ValueError("Invalid email")
    if total_cents < 0:
        raise ValueError("Invalid amount")
    # Process...

# ✅ Use value objects
from dataclasses import dataclass

@dataclass
class Email:
    address: str

    def __post_init__(self):
        if '@' not in self.address:
            raise ValueError("Invalid email")

@dataclass
class Money:
    cents: int

    def __post_init__(self):
        if self.cents < 0:
            raise ValueError("Amount cannot be negative")

    @property
    def dollars(self):
        return self.cents / 100

@dataclass
class OrderId:
    value: str

def process_order(order_id: OrderId, email: Email, total: Money):
    # Validation is built into the types
    # Process...
```

**Refactoring:** Replace Data Value with Object, Introduce Value Object

### Pattern 12: Long Parameter List

**Description:** Functions with too many parameters.

**Impact:** Hard to understand, remember, and use correctly.

**Example:**
```python
# ❌ Long parameter list
def create_invoice(
    customer_id,
    customer_name,
    customer_email,
    items,
    subtotal,
    tax_rate,
    tax_amount,
    discount_code,
    discount_amount,
    shipping_cost,
    total,
    payment_method,
    billing_address,
    shipping_address
):
    pass

# ✅ Use parameter objects
from dataclasses import dataclass
from typing import List

@dataclass
class Customer:
    id: str
    name: str
    email: str

@dataclass
class InvoiceDetails:
    items: List[object]
    subtotal: float
    tax_rate: float
    tax_amount: float
    discount_code: str
    discount_amount: float
    shipping_cost: float
    total: float

@dataclass
class PaymentInfo:
    method: str
    billing_address: str
    shipping_address: str

def create_invoice(customer: Customer, details: InvoiceDetails, payment: PaymentInfo):
    pass
```

**Refactoring:** Introduce Parameter Object, Preserve Whole Object

### Pattern 13: Shotgun Surgery

**Description:** Single change requires modifications across many classes.

**Impact:** Easy to miss changes, high risk of bugs.

**Example:**
```python
# ❌ Shotgun surgery - adding a new payment method requires changes everywhere
class OrderProcessor:
    def process(self, order):
        if order.payment_method == 'credit_card':
            # handle credit card
        elif order.payment_method == 'paypal':
            # handle paypal
        # Need to add cash here

class InvoiceGenerator:
    def generate(self, order):
        if order.payment_method == 'credit_card':
            # credit card invoice
        elif order.payment_method == 'paypal':
            # paypal invoice
        # Need to add cash here

class Receipt:
    def create(self, order):
        if order.payment_method == 'credit_card':
            # credit card receipt
        elif order.payment_method == 'paypal':
            # paypal receipt
        # Need to add cash here

# ✅ Use polymorphism
from abc import ABC, abstractmethod

class PaymentMethod(ABC):
    @abstractmethod
    def process(self, amount): pass

    @abstractmethod
    def generate_invoice(self): pass

    @abstractmethod
    def create_receipt(self): pass

class CreditCardPayment(PaymentMethod):
    def process(self, amount): pass
    def generate_invoice(self): pass
    def create_receipt(self): pass

class PayPalPayment(PaymentMethod):
    def process(self, amount): pass
    def generate_invoice(self): pass
    def create_receipt(self): pass

class CashPayment(PaymentMethod):  # Just add one new class
    def process(self, amount): pass
    def generate_invoice(self): pass
    def create_receipt(self): pass

class OrderProcessor:
    def process(self, order):
        order.payment_method.process(order.total)
```

**Refactoring:** Move Method, Inline Class, Replace Conditional with Polymorphism

### Pattern 14: Lazy Class

**Description:** Class that doesn't do enough to justify its existence.

**Impact:** Unnecessary complexity, maintenance overhead.

**Example:**
```python
# ❌ Lazy class
class UserNameFormatter:
    def format(self, name):
        return name.strip().title()

class User:
    def __init__(self, name):
        formatter = UserNameFormatter()
        self.name = formatter.format(name)

# ✅ Inline the class
class User:
    def __init__(self, name):
        self.name = name.strip().title()
```

**Refactoring:** Inline Class, Collapse Hierarchy

## Detection Strategies

### Metrics-Based Detection

**Function/Method Complexity:**
- Lines of code > 50
- Cyclomatic complexity > 10
- Nesting depth > 4
- Parameters > 5

**Class Complexity:**
- Methods > 15 (large class)
- Methods > 20 (god class)
- Fields > 10
- Dependencies > 7

**Code Duplication:**
- Identical code blocks > 5 lines
- Similar code with minor variations
- Token-based similarity > 80%

### Pattern-Based Detection

**Look for:**
- Multiple methods accessing same external data (Feature Envy)
- Same parameter groups (Data Clumps)
- Primitive types for domain concepts (Primitive Obsession)
- Direct field access between classes (Inappropriate Intimacy)
- Long if-else chains on type (Switch Statements smell)

### Tool-Based Detection

**Python tools:**
- `radon` - Cyclomatic complexity, maintainability index
- `pylint` - General code quality
- `flake8` - Style and quality
- `mccabe` - Complexity checker
- `vulture` - Dead code
- `bandit` - Security issues

## Prioritization

**High Priority (Fix Soon):**
- God classes
- Shotgun surgery
- Feature envy
- Long parameter lists

**Medium Priority (Plan Refactoring):**
- Large classes
- Duplicate code
- Data clumps
- Primitive obsession

**Low Priority (Nice to Have):**
- Magic numbers
- Lazy classes
- Long method names
- Inconsistent naming

Files in this skill

  • README.md884 B
  • skill.md16.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.