The biggest risk in refactoring is not making a mistake, but changing something without knowing what it affects. The core of this skill: build a safety net first, then operate, with a rollback point at every step.
Step 1: Determine whether this skill is needed
收到重构请求
│
├─ 改动 ≤2 个文件,不涉及公共接口?
│ └─ 直接动手,不需要本 skill
│
├─ 改动 3-5 个文件,局部重构?
│ └─ 走简化流程:第二步(快速版)→ 第四步 → 第五步
│
└─ 涉及公共接口 / 跨模块 / 架构调整 / 数据结构变更?
└─ 走完整流程:第二步 → 第三步 → 第四步 → 第五步 → 第六步
Decision signals:
| Signal | Use the full process |
|---|---|
| Change the signature of a public function/class | Yes |
| Split or merge modules | Yes |
| Change the data model/database schema | Yes |
| Change the directory structure | Yes |
| Change import paths referenced in multiple places | Yes |
| Purely internal implementation optimization, interface unchanged | No, simplify the process |
Step 2: Impact analysis
Before starting, first figure out "what will be affected by changing this."
2.1 Determine the refactoring scope
- Refactoring goal: What should be changed? What should it look like after the change? (Use
AskUserQuestionto align with the user) - Trigger reason: Why refactor? (technical debt / performance / maintainability / forced by new requirements)
- What not to change: Clearly identify which related code will not be touched this time (to prevent scope creep)
2.2 Sort out dependencies
For the module to be refactored, sort out upstream and downstream dependencies:
被谁调用(上游)→ [重构目标] → 调用了谁(下游)
Specific operations:
- Grep search: Search for the function name/class name/module path to be refactored, and find all reference locations
- Import analysis: Check
import/requirerelationships, and draw a dependency graph - Data flow tracing: If data structure changes are involved, trace where the data comes from and where it goes
2.3 Impact assessment
List the impact checklist:
## 影响分析
### 直接影响(必须改)
- `src/services/auth.ts` — 调用了要重构的函数
- `src/api/user.ts` — 引用了要修改的类型
### 间接影响(需要验证)
- `src/pages/login.tsx` — 依赖 auth 服务,接口不变则不受影响
- `tests/auth.test.ts` — 测试用例需要同步更新
### 不受影响(确认安全)
- `src/utils/format.ts` — 无依赖关系
Quick version(local refactoring): only do a Grep search to confirm the reference scope; a complete impact checklist document is not needed.
Step 3: Build a safety net
Refactoring without a safety net is gambling. Safety net = tests + rollback capability.
3.1 Confirm existing test coverage
Check whether the module to be refactored has tests:
# 找到相关测试文件
grep -r "重构目标函数名/模块名" tests/ __tests__/ *.test.* *.spec.*
| Existing test situation | Strategy |
|---|---|
| Tests exist and cover the core paths | First run the existing tests and confirm the baseline is all green |
| Tests exist but coverage is insufficient | Add tests for key paths before starting refactoring |
| No tests | Tests must be added first, at least covering core paths and edge cases |
3.2 Add missing tests
For cases with no tests or insufficient coverage:
- There is no need to pursue 100% coverage
- Focus coverage on:The core inputs and outputs of the function to be changed、The contract of public interfaces、Edge cases
- Tests should verify behavior (input→output), not implementation details
- Record test cases to
docs/tests/<模块名>-refactor.md
3.3 Create a rollback point
# 在重构开始前创建一个明确的 commit 或 branch
git checkout -b refactor/<模块名>
git commit -m "chore: 重构前基线 — 测试全绿"
Make sure you can git diff refactor/<模块名> see all changes at any time, and quickly roll back if something goes wrong.
Step 4: Step-by-step refactoring
An elephant must be eaten one bite at a time. Each step is verifiable and rollback-able.
4.1 Formulate a refactoring plan
Split the refactoring intoindependent, verifiable small steps, and tests should pass after each step:
## 重构计划
- [ ] Step 1: <描述> — 预期:测试全绿,行为不变
- [ ] Step 2: <描述> — 预期:测试全绿,行为不变
- [ ] Step 3: <描述> — 预期:测试全绿,新接口生效
- [ ] Step 4: 清理旧代码 — 预期:测试全绿,无废弃代码
Splitting principles:
- Each step does only one thing (change structure without changing logic / change logic without changing structure)
- After each step, it can compile and pass tests
- Steps should depend on each other as little as possible
- Dangerous operations (deleting code, changing data structures) go later, and are done only after confirming safety
4.2 Common refactoring strategies
| Scenario | Recommended strategy |
|---|---|
| Change a public interface signature | New first, then delete: new interface → migrate callers → delete old interface |
| Split large files/large functions | Extract → inline references → verify → delete old |
| Change directory structure | Move files first → fix imports → verify → commit(a separate step, do not mix in logic changes) |
| Replace dependencies/frameworks | Adapter pattern: old and new coexist → migrate gradually → remove old dependency |
| Change the data model | Dual-write transition: old and new fields coexist → migrate read/write logic → clean up old fields |
4.3 Execution discipline
After completing each step:
- Run tests: confirm all existing tests pass
- Run lint: confirm no formatting issues were introduced
- Quick review: take a look at the diff and confirm only what should be changed was changed
- Commit: one commit per step, with a message that clearly states what was done
git commit -m "refactor(auth): step 1 — 提取 token 验证为独立函数"
If tests fail at some step:
- First check whether the tests themselves need to be updated (because the interface changed)
- If it fails unexpectedly → stop and analyze, do not force yourself to continue
- If you really cannot figure it out → roll back to the previous step's commit and rethink the strategy
Step 5: Regression verification
The goal of refactoring is "same behavior, better structure." Verify whether the behavior really has not changed.
5.1 Run the full test suite
# 项目测试
npm test # 或 pytest
# 如果有 e2e 测试
npm run test:e2e
5.2 Manually verify critical paths
Tests cannot cover everything. For the following scenarios, verify manually:
- Whether page rendering is normal (frontend refactoring)
- Whether API responses match expectations (backend refactoring)
- Critical business processes work end to end (end-to-end)
5.3 Comparison verification
# 对比重构前后的 git diff,确认改动范围符合预期
git diff refactor/<模块名>..HEAD --stat
Check:
- No unrelated changes are mixed in
- No debug code is left behind
- No commented-out old code is left behind
Step 6: Wrap-up
6.1 Cleanup
- Delete obsolete old code (not comment it out, delete it)
- Update related documentation (if the refactoring changed directory structure, interfaces, configurations, etc.)
- Update
docs/tests/test cases in (tests added during the refactoring should be retained)
6.2 Hand over to task-finish for CR self-check
After the refactoring is complete, hand it over to task-finish for an in-depth self-check:
- Does the scope of changes match the refactoring goals?
- Are any unrelated changes mixed in?
- Is there any leftover debug code?
6.3 Retrospective and lessons learned (triggered by task-manager)
After the refactoring is complete, when the user marks the requirement as done, task-manager triggers the retrospective. For refactoring tasks, it is recommended to conduct a full retrospective and record it in docs/decisions/:
- Have the motivations and goals of the refactoring been achieved?
- Which steps went smoothly? Which got stuck?
- Was the impact analysis accurate? What was missed?
- What experience from similar refactorings can be reused next time?
Interfaces with other skills
task-start
│ 判定为重构任务
↓
refactoring(本 skill)
│
├─ 第二步 ← dependency-map(影响分析,如果有的话)
├─ 第二步 ← writing(写重构方案,大型重构时)
├─ 第四步 ← task-execute(跨会话进度管理)
├─ 第五步 ← perf-profiling(性能相关重构时对比前后)
│
├─ 收尾 → task-finish(CR 自检)
└─ 需求标 done → task-manager → 触发复盘
Anti-pattern list
| Anti-pattern | Consequence | Correct approach |
|---|---|---|
| Start changing without a safety net | After the changes, you don't know what broke | Confirm test coverage first, then start |
| Change too much at once | When problems occur, you can't pinpoint them | Commit in small steps, each step verifiable |
| Add features while refactoring | Scope creep, compounded risk | Do refactoring and feature development separately |
| Change logic while changing structure | Unable to distinguish whether problems are caused by structural changes or logic changes | Do only one thing at a time |
| Comment out old code without deleting it | The code gets dirtier and dirtier | Delete it once you're sure it's no longer needed |
| Skip regression testing | Problems are only discovered after release | Run tests at each step, and do a full regression at the end |
| Don't record the impact scope | Next time you change the same place, you again don't know who it affects | Write down the impact analysis |