Skip to content

11.4 大规模重构与迁移

跨 200 个文件的安全改造法。核心是"分批 + 验证 + 隔离"。

读完你能做什么:把一个吓人的大重构,拆成一系列可验证、可回滚的小步骤。


核心原则

大重构失败的根源几乎都是:一次改太多,出了问题无法定位,也无法回滚。

三条铁律:

text
1. 分批:永远不要一次改完,拆成可独立验证的批次
2. 验证:每批之后必须验证没破坏东西
3. 隔离:在 worktree 里做,失败不影响主线

第 1 步:在隔离环境开始

bash
# 在独立 worktree 里做,主工作区不受影响
claude -w big-refactor

失败了直接 claude rm big-refactor,主分支毫发无损(见 06.7)。


第 2 步:先建"安全网"

重构的前提是有测试保护。 没有测试的重构等于蒙眼开车。

text
> 在开始重构前,先评估安全网:
  1. 要重构的这些代码,现有测试覆盖如何?
  2. 覆盖不足的关键路径,先补测试(这些测试保证重构前后行为一致)
  3. 记录当前的行为基线(关键输入的输出)

  在安全网建好之前,不要动生产代码。

第 3 步:规划批次

text
> /plan
text
<task>
把整个代码库的回调风格(callback)迁移到 async/await,涉及约 200 个文件。
</task>

<instructions>
先规划,不要改。给我一个分批计划:
1. 按什么维度分批(模块?依赖层级?)
2. 每批包含哪些文件,为什么这样分
3. 批次之间的依赖顺序(哪些必须先做)
4. 每批如何独立验证
5. 每批的回滚方案

原则:每批要小到能在一次 review 里看完,且能独立验证和回滚。
</instructions>

分批的常见维度

维度适合
按模块模块边界清晰时
按依赖层级从叶子节点往上,或从底层往上
按文件数每批固定 10-20 个文件
按风险先低风险练手,再啃硬骨头

第 4 步:逐批执行

text
> 执行第 1 批(叶子模块,5 个文件):
  1. 迁移这 5 个文件
  2. 跑相关测试,确认行为不变
  3. 跑完整测试套件,确认没影响其他部分
  4. 独立 commit
  5. 停下来让我 review,确认后再下一批

不要提前开始第 2 批。

用脚本处理机械性批量改动

有些迁移是高度机械的(比如统一的 API 替换)。这种可以半自动化:

text
> 这批迁移是机械的:把所有 `oldApi.foo(cb)` 改成 `await newApi.foo()`。
  先在一个文件上做,让我确认模式对了。
  确认后,你对这批其余文件应用同样的模式,每个文件改完立即跑该文件的测试。

第 5 步:每批的验证门禁

用 hook 强制每批都通过验证(见 06.5):

bash
#!/usr/bin/env bash
# 每次 commit 前强制跑测试
CMD=$(jq -r '.tool_input.command // empty')
if echo "$CMD" | grep -qE '^git commit'; then
  if ! npm test > /tmp/t.log 2>&1; then
    jq -n '{hookSpecificOutput: {hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "测试未过,禁止提交此批次"}}'
    exit 0
  fi
fi
exit 0

这确保没有一个批次能在测试失败的情况下提交


第 6 步:处理跨批次的破坏

大重构中,某批可能悄悄破坏了之前的批次。

text
> 每完成 3 个批次,跑一次完整回归:
  1. 完整测试套件
  2. 对比行为基线(第 2 步记录的),确认关键路径输出没变
  3. 如果发现回归,用 git bisect 定位是哪一批引入的

大迁移的会话续航

200 个文件的迁移不可能一个会话做完。用外部状态文件(见 03.4):

markdown
<!-- MIGRATION.md -->
# async/await 迁移进度

## 已完成
- [x] 批次 1:utils 模块(5 文件)commit a1b2
- [x] 批次 2:data 层(8 文件)commit c3d4

## 进行中
- [ ] 批次 3:service 层(12 文件)
      卡点:orderService 依赖一个还没迁移的第三方回调

## 待办
- [ ] 批次 4-15...

## 约定
- 每批独立可回滚
- 接口签名不变
- 每批必须全套件通过才提交

CLAUDE.md 里指向它,新会话读一下就能接上。


完整流程速览

text
1. 隔离       worktree 里做
2. 安全网     补测试 + 记录基线
3. 规划批次   小、可独立验证、可回滚
4. 逐批执行   改 → 测 → commit → review
5. 验证门禁   hook 强制每批测试通过
6. 定期回归   每 3 批全量回归 + bisect
   (全程用 MIGRATION.md 存状态)

常见错误

错误后果对策
一次改 200 个文件出错无法定位分批
没有测试就重构不知道有没有改坏先建安全网
不在隔离环境失败污染主线worktree
批次太大review 看不完小到一次能看完
不定期回归后批悄悄破坏前批每几批全量回归
状态全在上下文会话断了就乱MIGRATION.md

延伸阅读

基于 VitePress 构建 · 内容采用原作者授权