| name | refactoring-patterns |
| description | Patterns for safe behavior-preserving refactoring — extract, rename, move, simplify — with test-baseline and rollback guidance. Trigger on refactor or restructure requests. |
| context | fork |
| user-invocable | false |
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.
def calculate_total(items):
total = 0
for item in items:
total += item.price * item.quantity
return total
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
pytest --cov=module_to_refactor --cov-report=term-missing
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
pytest
git diff HEAD~1 --stat
git diff HEAD~1 path/to/file.py
Common Refactorings
Extract Method
def process_order(order):
if not order.items:
raise ValueError("Order has no items")
if order.total <= 0:
raise ValueError("Order total must be positive")
discount = 0
if order.customer.is_premium:
discount = order.total * 0.1
payment = Payment(amount=order.total - discount)
payment.process()
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
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}"
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
grep -rn "old_name" --include="*.py"
sed -i 's/old_name/new_name/g' path/to/files/*.py
pytest
Safety Checklist
Before refactoring:
During refactoring:
After refactoring:
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 |