Refactoring
Restructure code while preserving exact behavior — extract a module, move a class to its better
home, redraw a dependency boundary, split or merge files. The goal is a codebase that is easier to
evolve, not fewer lines or prettier names. Every move is behavior-preserving and test-pinned.
When to use
- Extracting a module or class from inline code to redraw a boundary
- Moving a function/class to where it has the most context (Feature Envy fix at structure level)
- Splitting one oversized file/module into cohesive units, or merging near-duplicates into one
- Changing a dependency direction — inverting, decoupling, replacing a concrete dep with an interface
- Preparing a codebase for a feature by reshaping it first (then implement separately)
- Triggers on "refactor structure", "extract module", "move class", "split file", "change dependency", "重构结构", "提取模块", "拆分文件", "改依赖图"
Not for: single-file clarity cleanup — renaming, nesting, dead-code removal (use simplify); producing an architecture audit or design doc without executing the change (use codebase-design); machine-detectable lint/style issues (use linting).
Steps
1. Pin behavior before moving anything
Refactoring is behavior-preserving by definition — if behavior can shift, you're not refactoring,
you're rewriting. Pin it first:
- Run the test suite; it must be green. If it isn't, stop — fix the breakage or establish the baseline separately.
- If the area has weak coverage, add characterization tests that capture current behavior (inputs → observed outputs) before you touch structure. You're not testing what it should do; you're pinning what it does do so the refactor can't silently change it.
- Note any behavior you suspect is accidental (a bug tests currently encode). Don't fix it here — refactoring preserves behavior, bugs included. File it; fix it in a separate change.
2. Name the structural move
State the move in one sentence before executing. The catalog:
- Extract — pull a cohesive responsibility out into its own module/class/function behind a named interface.
- Move — relocate a function/class to where it has the most context (where its data lives).
- Split — break an oversized file/module along a cohesive seam into smaller units.
- Merge — fold near-duplicates into one canonical implementation.
- Change dependency — invert a dependency, decouple via interface, or replace a concrete dependency with a port.
For before→after examples and characterization-test guidance per move, load references/refactoring-catalog.md.
If you can't name it as one of these, it's probably clarity cleanup (→ simplify) or a design question (→ codebase-design).
3. Plan the move as the smallest behavior-preserving steps
Decompose the move into steps small enough that each one leaves the codebase green. "Extract module"
is not one step — it's: create the empty module → move one responsibility → update callers → run
tests → move the next. Large structural moves done in one pass are where regressions hide.
- At scale or for the separate-PR/incremental rules, follow §9 (behavior-preserving change discipline) in engineering-principles.md.
4. Execute incrementally — test after every step
One step, then the full suite, then the next step. Never batch structural changes into one untested
commit.
- Make the move → run the suite → pass: continue; fail: revert the step and reconsider.
- The separate-PR and Rule-of-500 rules are in §9 (behavior-preserving change discipline) of engineering-principles.md.
5. Verify the structure improved
Step back and compare before and after:
- Is the boundary cleaner? Do callers depend on less?
- Did the move concentrate complexity (good) or just relocate it (no gain)?
- Is the diff reviewable as a pure structural change — no behavior drift mixed in?
If the "refactored" structure is not clearly better, or the diff entangles behavior changes, revert. Not every refactor improves things.
Verify
Red flags: tests modified to pass after the move (behavior shifted); a "refactor" PR that also fixes a bug or adds a feature; large structural change in one untested pass; moving code without pinning behavior first; a refactor that leaves complexity merely relocated, not reduced.
References
- ${CLAUDE_PLUGIN_ROOT}/references/engineering-principles.md — shared discipline (verify don't assume, surgical scope, enforce simplicity)
- references/refactoring-catalog.md — before→after examples + characterization-test guidance for each move (extract, move, split, merge, change-dependency)
1---2name: refactoring3description: Use when restructuring code without changing behavior — extract modules, move classes, redraw dependency boundaries, split or merge files. Behavior-preserving structural changes that make the codebase easier to evolve, distinct from single-file clarity cleanup. Triggers on "refactor structure", "extract module", "move class", "split file", "change dependency", "重构结构", "提取模块", "拆分文件", "改依赖图". Not for single-file clarity cleanup (use simplify), architecture audit producing a design doc (use codebase-design), or lint/style fixes (use linting).4---56# Refactoring78Restructure code while preserving exact behavior — extract a module, move a class to its better9home, redraw a dependency boundary, split or merge files. The goal is a codebase that is easier to10evolve, not fewer lines or prettier names. Every move is behavior-preserving and test-pinned.1112## When to use1314- Extracting a module or class from inline code to redraw a boundary15- Moving a function/class to where it has the most context (Feature Envy fix at structure level)16- Splitting one oversized file/module into cohesive units, or merging near-duplicates into one17- Changing a dependency direction — inverting, decoupling, replacing a concrete dep with an interface18- Preparing a codebase for a feature by reshaping it first (then implement separately)19- Triggers on "refactor structure", "extract module", "move class", "split file", "change dependency", "重构结构", "提取模块", "拆分文件", "改依赖图"2021**Not for:** single-file clarity cleanup — renaming, nesting, dead-code removal (use `simplify`); producing an architecture audit or design doc without executing the change (use `codebase-design`); machine-detectable lint/style issues (use `linting`).2223## Steps2425### 1. Pin behavior before moving anything2627Refactoring is behavior-preserving by definition — if behavior can shift, you're not refactoring,28you're rewriting. Pin it first:2930- Run the test suite; it must be green. If it isn't, stop — fix the breakage or establish the baseline separately.31- If the area has weak coverage, add **characterization tests** that capture current behavior (inputs → observed outputs) before you touch structure. You're not testing what it *should* do; you're pinning what it *does* do so the refactor can't silently change it.32- Note any behavior you suspect is accidental (a bug tests currently encode). Don't fix it here — refactoring preserves behavior, bugs included. File it; fix it in a separate change.3334### 2. Name the structural move3536State the move in one sentence before executing. The catalog:3738- **Extract** — pull a cohesive responsibility out into its own module/class/function behind a named interface.39- **Move** — relocate a function/class to where it has the most context (where its data lives).40- **Split** — break an oversized file/module along a cohesive seam into smaller units.41- **Merge** — fold near-duplicates into one canonical implementation.42- **Change dependency** — invert a dependency, decouple via interface, or replace a concrete dependency with a port.4344For before→after examples and characterization-test guidance per move, load `references/refactoring-catalog.md`.4546If you can't name it as one of these, it's probably clarity cleanup (→ `simplify`) or a design question (→ `codebase-design`).4748### 3. Plan the move as the smallest behavior-preserving steps4950Decompose the move into steps small enough that each one leaves the codebase green. "Extract module"51is not one step — it's: create the empty module → move one responsibility → update callers → run52tests → move the next. Large structural moves done in one pass are where regressions hide.5354- At scale or for the separate-PR/incremental rules, follow §9 (behavior-preserving change discipline) in engineering-principles.md.5556### 4. Execute incrementally — test after every step5758One step, then the full suite, then the next step. Never batch structural changes into one untested59commit.6061- Make the move → run the suite → pass: continue; fail: revert the step and reconsider.62- The separate-PR and Rule-of-500 rules are in §9 (behavior-preserving change discipline) of engineering-principles.md.6364### 5. Verify the structure improved6566Step back and compare before and after:6768- Is the boundary cleaner? Do callers depend on less?69- Did the move concentrate complexity (good) or just relocate it (no gain)?70- Is the diff reviewable as a pure structural change — no behavior drift mixed in?7172If the "refactored" structure is not clearly better, or the diff entangles behavior changes, revert. Not every refactor improves things.7374## Verify7576- [ ] Test suite green before and after, with no test modifications (modified tests mean behavior changed)77- [ ] Each step is an independently revertible, behavior-preserving change; the diff is purely structural78- [ ] The structural move is named (extract / move / split / merge / change-dependency) and the result concentrates complexity rather than relocating it79- [ ] No behavior change mixed in — bugs observed during the refactor are filed, not silently fixed80- [ ] Behavior-preserving change discipline followed (§9: incremental, separate-PR, Rule-of-500)8182**Red flags:** tests modified to pass after the move (behavior shifted); a "refactor" PR that also fixes a bug or adds a feature; large structural change in one untested pass; moving code without pinning behavior first; a refactor that leaves complexity merely relocated, not reduced.8384## References8586- [${CLAUDE_PLUGIN_ROOT}/references/engineering-principles.md](${CLAUDE_PLUGIN_ROOT}/references/engineering-principles.md) — shared discipline (verify don't assume, surgical scope, enforce simplicity)87- [references/refactoring-catalog.md](references/refactoring-catalog.md) — before→after examples + characterization-test guidance for each move (extract, move, split, merge, change-dependency)