refactoring-patterns

jayteealao's avatarfrom jayteealao

This skill provides patterns for safe, systematic refactoring including extract, rename, move, and simplification operations with proper testing and rollback strategies.

⭐0stars🔀0forks📁View on GitHub🕐Updated Jan 9, 2026⬇️2downloads

When & Why to Use This Skill

The Refactoring Patterns skill provides a systematic framework for improving code quality and maintainability without altering external behavior. It focuses on reducing technical debt through safe, incremental structural changes such as method extraction, identifier renaming, and logic simplification, all supported by rigorous testing and rollback strategies to ensure codebase stability.

Use Cases

  • Eliminating code smells by decomposing long methods and bloated classes into modular, reusable components.
  • Executing safe, large-scale renaming and moving of code entities across complex projects with automated verification.
  • Modernizing legacy codebases by replacing complex conditional logic with polymorphism and simplifying nested structures.
  • Implementing a test-driven refactoring workflow to ensure zero regressions while improving code readability and architecture.
  • Reducing cyclomatic complexity in critical modules to lower maintenance costs and improve developer onboarding speed.
namerefactoring-patterns
descriptionThis skill provides patterns for safe, systematic refactoring including extract, rename, move, and simplification operations with proper testing and rollback strategies.

Refactoring Patterns Skill

Systematic refactoring with safety checks and verification.

When to Use

  • Extracting methods, classes, or modules
  • Renaming identifiers safely across codebase
  • Moving code between files or modules
  • Simplifying complex code
  • Modernizing legacy patterns

Reference Documents

Core Principles

1. Never Refactor Without Tests

BEFORE refactoring:
1. Ensure tests exist for code being changed
2. Run tests to confirm they pass
3. Note coverage percentage

DURING refactoring:
4. Run tests after each small change
5. Keep changes atomic and reversible

AFTER refactoring:
6. Run full test suite
7. Verify coverage didn't decrease

2. Small, Incremental Changes

BAD:  One massive PR that changes everything
GOOD: Series of small PRs, each working state

Commit 1: Add new class
Commit 2: Add tests for new class
Commit 3: Migrate first usage
Commit 4: Migrate remaining usages
Commit 5: Remove old code

3. Preserve Behavior

Refactoring changes structure, not behavior.

# BEFORE
def calculate_total(items):
    total = 0
    for item in items:
        total += item.price * item.quantity
    return total

# AFTER (same behavior, different structure)
def calculate_total(items):
    return sum(item.price * item.quantity for item in items)

Refactoring Workflow

Step 1: Identify the Smell

Code Smell Refactoring
Long method Extract Method
Large class Extract Class
Duplicated code Extract Method/Class
Long parameter list Introduce Parameter Object
Data clumps Extract Class
Primitive obsession Replace Primitive with Object
Switch statements Replace with Polymorphism
Parallel inheritance Collapse Hierarchy

Step 2: Ensure Test Coverage

# Check current coverage
pytest --cov=module_to_refactor --cov-report=term-missing

# If coverage < 80%, add tests first
pytest tests/test_module.py -v

Step 3: Apply Refactoring

Execute refactoring in small steps:

Extract Method Example:
1. [ ] Identify code to extract
2. [ ] Create new method with extracted code
3. [ ] Replace original code with method call
4. [ ] Run tests
5. [ ] Commit

Step 4: Verify

# Run tests
pytest

# Check for regressions
git diff HEAD~1 --stat

# Review changes
git diff HEAD~1 path/to/file.py

Common Refactorings

Extract Method

# BEFORE
def process_order(order):
    # Validate order
    if not order.items:
        raise ValueError("Order has no items")
    if order.total <= 0:
        raise ValueError("Order total must be positive")

    # Calculate discount
    discount = 0
    if order.customer.is_premium:
        discount = order.total * 0.1

    # Process payment
    payment = Payment(amount=order.total - discount)
    payment.process()

# AFTER
def process_order(order):
    validate_order(order)
    discount = calculate_discount(order)
    process_payment(order, discount)

def validate_order(order):
    if not order.items:
        raise ValueError("Order has no items")
    if order.total <= 0:
        raise ValueError("Order total must be positive")

def calculate_discount(order):
    if order.customer.is_premium:
        return order.total * 0.1
    return 0

def process_payment(order, discount):
    payment = Payment(amount=order.total - discount)
    payment.process()

Extract Class

# BEFORE
class Order:
    def __init__(self):
        self.items = []
        self.shipping_address_line1 = ""
        self.shipping_address_line2 = ""
        self.shipping_city = ""
        self.shipping_state = ""
        self.shipping_zip = ""
        self.shipping_country = ""

    def format_shipping_address(self):
        return f"{self.shipping_address_line1}\n{self.shipping_city}, {self.shipping_state}"

# AFTER
class Address:
    def __init__(self, line1, line2, city, state, zip_code, country):
        self.line1 = line1
        self.line2 = line2
        self.city = city
        self.state = state
        self.zip_code = zip_code
        self.country = country

    def format(self):
        return f"{self.line1}\n{self.city}, {self.state}"

class Order:
    def __init__(self):
        self.items = []
        self.shipping_address = None

Rename

# Safe rename using IDE/tools
# In VS Code: F2 on symbol
# In PyCharm: Shift+F6

# Manual rename with verification
grep -rn "old_name" --include="*.py"
# Replace all occurrences
sed -i 's/old_name/new_name/g' path/to/files/*.py
# Run tests
pytest

Safety Checklist

Before refactoring:

  • Tests exist and pass
  • Coverage is adequate (>80%)
  • Changes are scoped and understood
  • Rollback plan exists

During refactoring:

  • Make one change at a time
  • Run tests after each change
  • Commit working states

After refactoring:

  • All tests pass
  • Coverage maintained or improved
  • No behavior changes (unless intentional)
  • Code review completed

Quick Reference

Refactoring When to Use Risk
Rename Unclear names Low
Extract Method Long methods Low
Inline Method Unnecessary indirection Low
Extract Class Large class Medium
Move Method Method in wrong class Medium
Replace Conditional with Polymorphism Complex conditionals High
Change Method Signature API changes High