Refactor Process
Quick Reference
| Aspect | Rule |
|---|---|
| Pre-requisite | Characterization tests must exist and be Green before any edits |
| Step Size | One atomic transformation at a time (rename variable, extract method, etc.) |
| Verification | Run tests after every single step |
| No Behavior Changes | No new features, bug fixes, or changed return values during refactoring |
| Rollback | If tests turn Red, undo immediately — do not debug in a broken state |
Process Steps
Step 1: Establish the Baseline
- Run the existing tests for the class or module.
- If coverage is missing or weak, write characterization tests (tests that capture the current behavior, including edge cases and errors).
- Verify all tests are Green before proceeding.
Step 2: Plan the Steps
- Identify the goal (e.g., extract a complex method into its own class, simplify a conditional block).
- Break the goal into a sequence of atomic refactoring operations (rename, extract, inline, move, replace conditional, etc.).
Step 3: Execute and Verify Loop
For each planned step:
- Make the singular, atomic code modification.
- Run the tests.
- If Green, save/commit the step and proceed.
- If Red, discard the change (e.g., via
git checkoutor undo), analyze the root cause, and try a smaller step.
Checkpoint Pattern
Pause and align with the user:
- Baseline Checkpoint: Show the characterization tests and current implementation before making any edits.
- Refactoring Proposal: Outline the planned steps of transformations.
- Completion Checkpoint: Present the final refactored code and the test suite validation report.
Example Refactoring Loop (Extract Method)
Baseline (Green):
class ReportGenerator
def generate(data)
# Formats raw data to report
formatted = data.map { |row| "#{row[:id]}: #{row[:name].strip.capitalize}" }
# Renders report
"=== Report ===\n" + formatted.join("\n") + "\n=============="
end
end
Step 1: Extract Formatter Logic (Atomic Edit):
class ReportGenerator
def generate(data)
formatted = format_rows(data)
"=== Report ===\n" + formatted.join("\n") + "\n=============="
end
private
def format_rows(data)
data.map { |row| "#{row[:id]}: #{row[:name].strip.capitalize}" }
end
end
Action: Run tests immediately. Confirm Green.
Anti-Patterns
- Behavior Creep: Keep refactoring and behavior changes (bug fixes, optimizations) in completely separate commits.
- The "Giant Leap" Refactor: Multiple non-trivial changes at once make failures hard to diagnose; always take the smallest possible atomic step.
Integration
| Context | Next Skill |
|---|---|
| Establishing baseline coverage | test-planning-process → tdd-process |
| Documenting newly extracted APIs | write-yard-docs |
| Post-refactoring review | review-process |