| name | refactoring-judgment |
| description | When to refactor, what to refactor, how far to go. Technical debt classification, legacy code strategy, refactoring safety. Use when: deciding whether to refactor, scoping refactoring work, handling legacy code, classifying technical debt, choosing refactoring techniques. Triggers: refactoring, technical debt, code smell, legacy code, when to refactor, refactoring scope, debt payoff |
Refactoring judgment for deciding when, what, and how far to refactor. Covers debt classification, legacy code strategy, and safety discipline.
Definition
- Refactoring = restructuring existing code without changing observable behavior
- If behavior changes → not refactoring. Separate commits for behavior change vs restructuring.
When to Refactor (Rule of Three)
| Timing | Context | Name |
|---|
| Adding a feature | Make the change easy, then make the easy change | Prep refactoring |
| Fixing a bug | Understand the code before fixing | Comprehension refactoring |
| Code review | Small opportunistic improvements | Review-time refactoring |
- NOT scheduled "refactoring sprints" — refactoring is continuous, embedded in feature work
- Scratch refactoring: refactor freely to understand code, then discard. Purely for comprehension.
Code Smells → Refactoring Map
See references/code-smells.md for the full smell-signal-refactoring table.
Key principle: smells are signals, not rules. Identify the smell → pick the matching refactoring → apply in small steps.
Legacy Code Strategy (Feathers)
See references/legacy-code-techniques.md for detailed techniques.
- Legacy code = code without tests
- The Dilemma: need tests to refactor safely, need to refactor to add tests
- Break the cycle: characterization tests → find seams → sprout/wrap → incremental coverage
Technical Debt Quadrant (Fowler)
| Deliberate | Inadvertent |
|---|
| Prudent | "Ship now, pay later" — document & schedule | "Now we know better" — learn & improve |
| Reckless | "No time for design" — red flag, compounds fast | "What's layering?" — education problem |
When to Pay Off Debt
- Before adding features in the same area (prep refactoring)
- When debt actively slows the team (measure: bug frequency, change velocity in that area)
- When cost-of-living-with-it > cost-of-fixing
- NOT as a separate "debt sprint" decoupled from feature context
When NOT to Refactor
| Condition | Reason |
|---|
| Code works and is never modified | Stable legacy — leave it |
| Code will be replaced soon | Planned deprecation — wasted effort |
| No tests exist | Add characterization tests first |
| Time pressure for unrelated delivery | Creates more debt — defer |
Refactoring Safety Net
Pre-refactoring Checklist
- Tests exist (or write characterization tests first)
- Clean working tree in version control
- Scope defined — which smell / debt are you addressing?
- Behavior must NOT change (if it must → separate commit)
During Refactoring
- Small steps — each step compiles and passes tests
- Commit after each successful step
- Stuck → revert to last green commit
- Never refactor and change behavior in the same commit
After Refactoring
- Run full test suite
- Review diff — check for scope creep
- Document if refactoring reveals architectural insights
Refactoring Mechanics
- Each refactoring = series of small, behavior-preserving steps
- Run tests after every step
- Commit frequently
- Automated refactoring tools (IDE rename, extract, inline) preferred over manual edits
Anti-Patterns
| Pattern | Problem |
|---|
| Big Bang Rewrite | High risk, loses institutional knowledge, usually fails |
| Refactoring Sprint | Decoupled from feature work, hard to justify ROI |
| Refactoring without tests | Changes behavior unknowingly |
| Gold Plating | Refactoring beyond what current task needs |
| Refactoring Envy | Refactoring code you don't own or aren't working on |
Decision Heuristic
Is the code in your current task's path?
├─ No → Don't refactor (Refactoring Envy)
└─ Yes → Is it hard to understand or change?
├─ No → Don't refactor (YAGNI)
└─ Yes → Do tests exist?
├─ No → Write characterization tests first
└─ Yes → Refactor with small steps, commit often
Reference Books
- Refactoring: Improving the Design of Existing Code — Martin Fowler (2nd ed.)
- Working Effectively with Legacy Code — Michael Feathers
- Clean Code — Robert C. Martin (code smells chapters)
- The Pragmatic Programmer — Hunt & Thomas (Boy Scout Rule)