Code Refactoring
Quick Reference
- Templates: See templates.md for reporting refactoring results
Core Principle
NO REFACTORING WITHOUT TESTS FIRST
Refactor safely: tests first, incremental changes, verify behavior preserved.
When to Use
Use when encountering:
- Code duplication (DRY violations)
- Long functions (>50 lines)
- High complexity (cyclomatic complexity >10, nested conditionals)
- Placeholder functions (
pass,raise NotImplementedError) - Magic numbers/strings
- Deep nesting (>3 levels)
- Large classes (>300 lines, multiple responsibilities)
Don't refactor when:
- Code works correctly and is rarely touched
- Refactoring would break functionality without tests
- Time pressure requires shipping first (document debt, refactor later)
Safe Refactoring Workflow
Phase 1: Identify Target
Detect Code Smells
- Long functions (>50 lines)
- High complexity (>10 decision points)
- Duplication (similar code 2+ places)
- Placeholder functions
- Magic numbers/strings
- Deep nesting (>3 levels)
Understand Current Behavior
- Read code carefully
- Trace execution paths
- Identify dependencies
Assess Impact
- What code calls this?
- What tests exist?
- What would break?
Phase 2: Write Tests (If Missing)
REQUIRED: If no tests exist:
- Write tests capturing current behavior
- Run tests to establish baseline
- All tests must pass before refactoring
- Cover: happy path, errors, edge cases, boundaries
Phase 3: Refactor Incrementally
One change at a time:
- Make smallest possible change (extract one method, rename one variable)
- Run tests after each change (must pass)
- Commit frequently with clear messages
- Verify behavior unchanged
Phase 4: Verify
- Run all tests (must pass)
- Check code quality (linter, type checker)
- Document changes
Refactoring Patterns
Extract Method
When: Long function, duplicated code, complex logic
Process:
- Identify code block to extract
- Create new method with descriptive name
- Move code, replace with method call
- Run tests
Extract Class
When: Class has multiple responsibilities, large class
Process:
- Identify cohesive group of data/behavior
- Create new class
- Move fields and methods
- Delegate calls
- Run tests
Eliminate Duplication
When: Same code appears in multiple places
Process:
- Identify duplicated code
- Extract common code to method/class
- Parameterize differences
- Replace all occurrences
- Run tests
Replace Placeholder
When: Function has pass, raise NotImplementedError
Process:
- Check if function is called (YAGNI)
- If unused: Remove
- If used: Implement functionality
- Write tests
- Run tests
Reduce Complexity
When: High cyclomatic complexity, deeply nested conditionals
Process:
- Extract conditions to methods with descriptive names
- Use early returns/guard clauses
- Replace nested ifs with flat structure
- Consider polymorphism for type-based conditionals
- Run tests
Extract Constant
When: Magic numbers/strings in code
Process:
- Identify magic number/string
- Create constant with descriptive name
- Replace all occurrences
- Run tests
Code Smell Quick Reference
| Smell | Detection | Refactoring |
|---|---|---|
| Long function | >50 lines | Extract Method |
| High complexity | >10 decision points | Extract Method, Simplify Conditionals |
| Duplication | Same code 2+ places | Extract Method, Extract Class |
| Placeholder | pass, NotImplementedError |
Implement or Remove |
| Magic numbers | Unexplained constants | Extract Constant |
| Deep nesting | >3 levels | Extract Method, Early Return |
| Large class | >300 lines | Extract Class |
Red Flags - STOP and Reassess
- Refactoring without tests
- Multiple changes in one commit
- Tests failing after refactoring
- Changing behavior while refactoring
- Large refactoring without incremental steps
Integration with TDD
REQUIRED: Use testing skill before refactoring:
- If tests exist: Run them, ensure all pass
- If tests missing: Write tests using TDD workflow
- Refactor incrementally
- Run tests after each change
- All tests must pass before proceeding
Refactoring is part of TDD REFACTOR phase - improve code structure while keeping tests green.
Common Mistakes
| Mistake | Fix |
|---|---|
| Refactor without tests | Write tests first, establish baseline |
| Change behavior | Refactor = same behavior, better structure |
| Too many changes at once | One change per commit, test after each |
| Ignoring failing tests | Fix tests or revert refactoring |
The Bottom Line
Refactoring improves code without changing behavior.
Tests first. Incremental changes. Verify after each step. Preserve behavior always.