engineering
Refactoring Checklist
Safe refactoring procedures with pre/post verification — covering scope assessment, test coverage checks, incremental transformation, and regression prevention.
refactoringcode-qualitytechnical-debtsafe-changes
Works well with agents
Works well with skills
$ npx skills add The-AI-Directory-Company/(…) --skill refactoring-checklistrefactoring-checklist/
SKILL.md
Markdown
| 1 | |
| 2 | # Refactoring Checklist |
| 3 | |
| 4 | ## Before you start |
| 5 | |
| 6 | Gather the following before touching code: |
| 7 | |
| 8 | 1. **What are you refactoring?** — Specific file, module, function, or pattern |
| 9 | 2. **Why?** — Performance, readability, removing duplication, enabling a new feature, reducing complexity |
| 10 | 3. **What is the current test coverage?** — Run coverage report on the target code |
| 11 | 4. **What depends on this code?** — Callers, importers, API consumers, downstream services |
| 12 | 5. **What is the blast radius?** — If this breaks, who is affected? |
| 13 | 6. **Is there a deadline?** — Refactoring without time pressure is safer. If rushed, reduce scope. |
| 14 | |
| 15 | Do not refactor code you do not understand. Read it first, understand its intent and edge cases, then plan the change. |
| 16 | |
| 17 | ## Procedure |
| 18 | |
| 19 | ### 1. Verify test coverage before changing anything |
| 20 | |
| 21 | Run the existing test suite against the target code: |
| 22 | |
| 23 | ``` |
| 24 | COVERAGE BEFORE: |
| 25 | - Statements: [X%] |
| 26 | - Branches: [X%] |
| 27 | - Functions: [X%] |
| 28 | - Lines: [X%] |
| 29 | ``` |
| 30 | |
| 31 | If coverage is below 80%, write tests for the existing behavior BEFORE refactoring. These tests are your safety net — they verify the refactoring does not change behavior. |
| 32 | |
| 33 | Tests to add before refactoring: |
| 34 | - [ ] Happy path with typical inputs |
| 35 | - [ ] Edge cases: empty input, null, boundary values |
| 36 | - [ ] Error paths: what happens when things fail |
| 37 | - [ ] Integration points: verify interactions with dependencies |
| 38 | |
| 39 | ### 2. Define the target state |
| 40 | |
| 41 | Write down what the code should look like AFTER refactoring: |
| 42 | |
| 43 | ``` |
| 44 | CURRENT: [describe current structure] |
| 45 | TARGET: [describe target structure] |
| 46 | REASON: [why target is better — measurable if possible] |
| 47 | SCOPE: [exactly which files/functions change] |
| 48 | NOT CHANGING: [explicitly list what stays the same] |
| 49 | ``` |
| 50 | |
| 51 | ### 3. Make a refactoring plan |
| 52 | |
| 53 | Break the refactoring into small, independently verifiable steps. Each step should: |
| 54 | |
| 55 | - Be committable on its own |
| 56 | - Pass all tests after completion |
| 57 | - Not change external behavior |
| 58 | |
| 59 | Common step sequences: |
| 60 | |
| 61 | **Extract**: Identify code to extract -> Write tests for it -> Extract to new function/module -> Update callers -> Verify tests pass |
| 62 | |
| 63 | **Rename**: Find all references -> Rename in one commit -> Verify no broken references -> Update documentation |
| 64 | |
| 65 | **Simplify**: Identify the complexity -> Write tests covering all branches -> Simplify the logic -> Verify same behavior with simpler code |
| 66 | |
| 67 | **Move**: Identify the new location -> Create the target file -> Move code -> Update all imports -> Verify nothing broke |
| 68 | |
| 69 | ### 4. Execute one step at a time |
| 70 | |
| 71 | For each step in the plan: |
| 72 | |
| 73 | 1. Make the change |
| 74 | 2. Run the full test suite |
| 75 | 3. Review the diff — does it match your plan? |
| 76 | 4. Commit with a message describing the refactoring step |
| 77 | |
| 78 | Do NOT batch multiple refactoring steps into one commit. If something breaks, you need to know which step caused it. |
| 79 | |
| 80 | ### 5. Verify after completion |
| 81 | |
| 82 | Run the full verification: |
| 83 | |
| 84 | ``` |
| 85 | COVERAGE AFTER: |
| 86 | - Statements: [X%] (should be >= before) |
| 87 | - Branches: [X%] |
| 88 | - Functions: [X%] |
| 89 | - Lines: [X%] |
| 90 | |
| 91 | BEHAVIOR CHECK: |
| 92 | - [ ] All existing tests pass |
| 93 | - [ ] No new warnings or errors in build |
| 94 | - [ ] No changes to public API signatures (unless intentional) |
| 95 | - [ ] Performance benchmarks are within tolerance (if applicable) |
| 96 | - [ ] Dependent services/consumers are unaffected |
| 97 | ``` |
| 98 | |
| 99 | ### 6. Clean up |
| 100 | |
| 101 | After the refactoring is verified: |
| 102 | |
| 103 | - [ ] Remove any temporary scaffolding or compatibility shims |
| 104 | - [ ] Delete dead code that the refactoring replaced |
| 105 | - [ ] Update documentation if public interfaces changed |
| 106 | - [ ] Update related comments that reference the old structure |
| 107 | - [ ] Notify consumers if any API changes were made |
| 108 | |
| 109 | ## Safe refactoring patterns |
| 110 | |
| 111 | | Pattern | When to use | Risk level | |
| 112 | |---------|------------|------------| |
| 113 | | Rename variable/function | Name does not describe purpose | Low | |
| 114 | | Extract function | Block of code has a distinct responsibility | Low | |
| 115 | | Inline function | Function adds indirection without value | Low | |
| 116 | | Move to new file | File has too many responsibilities | Medium | |
| 117 | | Change function signature | Parameters are confusing or incomplete | Medium | |
| 118 | | Replace algorithm | Current implementation is incorrect or slow | High | |
| 119 | | Restructure module boundaries | Architecture needs to change | High | |
| 120 | |
| 121 | For high-risk refactoring, consider using a feature flag or parallel implementation that can be toggled. |
| 122 | |
| 123 | ## Quality checklist |
| 124 | |
| 125 | - [ ] Tests existed (or were written) BEFORE the refactoring started |
| 126 | - [ ] Each step was committed independently |
| 127 | - [ ] All tests pass after the refactoring |
| 128 | - [ ] Test coverage did not decrease |
| 129 | - [ ] No external behavior changed (unless that was the explicit goal) |
| 130 | - [ ] Dead code from the old implementation is removed |
| 131 | - [ ] The refactoring achieves the stated goal (measurably, if possible) |
| 132 | |
| 133 | ## Common mistakes |
| 134 | |
| 135 | - **Refactoring without tests.** If there are no tests, you have no way to verify the refactoring is behavior-preserving. Write tests first. |
| 136 | - **Changing behavior during a refactoring.** Refactoring changes structure, not behavior. If you need to fix a bug, do it in a separate commit before or after the refactoring. |
| 137 | - **Making the PR too large.** A refactoring PR with 50 files changed is hard to review and risky to merge. Break it into smaller PRs that each pass tests independently. |
| 138 | - **Refactoring code you do not understand.** If you cannot explain what the code does and why, you cannot safely change it. Read and understand first. |
| 139 | - **Not checking callers.** Changing a function signature without updating all callers produces runtime errors that tests may not catch if coverage is incomplete. |
| 140 | - **Skipping the "why."** Refactoring without a clear reason leads to churn. If you cannot articulate why the new structure is better, the refactoring may not be worth the risk. |
| 141 |