跳到主内容
refactorlegacysafemaintenance

Refactor Legacy Prompt:安全地给老代码动手术

让 AI 按「先锁行为、再小步改、每步可验证」的纪律重构遗留代码:列测试锚点、圈出高风险区、给出分步计划,禁止一次性大改写。强调保留外部行为、降低回归风险。

发布 2026-09-06

用法

把要重构的文件 / 模块贴进去,明确「目标」(降耦 / 提可读性 / 抽函数 / 去重复),让 AI 出一份可逐步执行、每步可回滚的重构计划。适合接手祖传代码、偿还技术债前先对齐方案。

什么时候用

  • 接手祖传模块、改动面大于你能在脑内模拟的范围——先让它出锚点与分步计划,再决定动不动。
  • 重构前需要和团队对齐方案——这份计划本身就是一份可评审的 RFC 草稿。
  • 代码没有测试但必须改——用「行为锚点」这一步逼出「先补什么最小测试」。
  • 想让 AI 在 Claude Code / Cursor 里自主跑多步重构——把「每步验证 + 回滚路径」写进提示词,是防止它一次性大改写的唯一有效手段。

什么时候别用

  • 目标本身就是改行为(加功能、改接口)——那是开发任务,不是重构。混在一起会让「行为没变」这条铁律失效。
  • 单文件、几十行、一眼看完的改动——直接改更快,走流程反而是负担。
  • 你已经知道该怎么改——提示词的价值在逼出你没想到的风险点;如果你已有完整方案,直接用 /review 校验即可。
  • 没有版本控制兜底——本模板的回滚策略依赖 git checkout,没进版本库的代码别用本模板。

Prompt

你是一位谨慎的重构专家。我要对下面的遗留代码做重构,目标是:{降耦 / 提升可读性 / 抽公共函数 / 消除重复 — 选 1,可补描述}。

# 铁律(不可违反)
1. 不改变外部可观察行为:输入输出、公共接口、副作用保持不变。
2. 小步前进:把改动拆成一系列独立、可编译、可单测的小步骤,禁止一次性大改写。
3. 每步可验证:明确这一步改完后跑哪条命令 / 哪个测试来确认没炸。
4. 不引入新依赖、不改目录结构、不顺手「优化」无关代码。

# 输出要求
- 第一步:先列出「行为锚点」——哪些已有测试 / 日志 / 接口能证明行为没变?没有就先建议补什么最小测试。
- 第二步:标出高风险区(隐式依赖、全局状态、被多处调用),这些区域最后动、最小动。
- 第三步:给出分步计划,每步格式:
  「步骤 N:{做什么}|风险:{low/mid/high}|验证:{命令/测试}|回滚:{git checkout 该文件}」
- 结尾给一句话总原则:本次重构的「绝不越过」的边界。

<粘贴代码 / 文件路径>

为什么有效

  • 「不改外部行为」铁律:把重构和「顺手加功能」切开,避免范围蔓延引入回归。
  • 行为锚点前置:没有测试覆盖的遗留代码直接重构 = 赌博;先逼出锚点降低风险。
  • 每步可回滚:小步 + git checkout 回滚路径,出问题立刻撤,不卡在半改写状态。
  • 高风险区最后动:全局状态、被多处引用的代码最易炸,放到计划末尾最小改动。

验收判据:怎么判断它给的方案能用

别看计划「写得好不好看」,看这六条。任何一条不满足,就把它打回去重写:

#判据不合格的典型表现
1行为锚点具体到可执行的命令写「有单元测试覆盖」却不给测试文件名与断言
2每一步都能单独编译 / 单独跑通出现「步骤 3 依赖步骤 5 的改动」这类交叉依赖
3每步都给了验证命令只有「改完后测试通过」这种无法执行的表述
4每步都给了回滚路径只写 git checkout 却不指明具体文件
5高风险区被单独标出并排在后面全局状态与高频调用函数混在普通步骤里
6没有夹带无关改动出现「顺便」「同时」「顺手」——这是范围蔓延的信号

最硬的一条验收是变异测试(mutation testing):如果你的行为锚点真的有效,故意改坏一处实现,测试应该失败。改坏了还全绿,说明锚点是假的,重构后的「没炸」也不作数。

# 以 Stryker(JS/TS)为例:锚点是否有效,用变异分数说话
npx stryker run --mutate "src/target-module/**/*.ts"
# 分数低 = 测试没真正锁住行为 → 先补测试再重构,别急着动代码

变异测试跑得慢、且对无断言的「烟雾测试」无效;小模块用、整库慎用。

变体 A / B / C

A · 只出计划不动手(评审用) —— 在铁律前加一句:

只输出重构计划,不要修改任何文件、不要输出完整改写后的代码。
计划里每步的文件路径必须是我仓库里真实存在的路径。

B · 边改边验(交给 agent 自主跑) —— 在输出要求末尾追加:

执行时严格按步骤串行推进:每完成一步立即运行该步的验证命令;
验证失败立即用该步的回滚路径撤销,然后停下报告原因,不要继续下一步。
全部步骤完成后,输出一张「步骤 / 验证结果 / 是否回滚」的汇总表。

C · 无测试遗留代码专用(先补锁再动刀) —— 把第一步换成:

第一步改为「先写锁定当前行为的特征测试(characterization test)」:
只描述代码现在实际做什么(包括看起来像 bug 的行为),不要修正它。
测试通过后再进入分步计划。

B 变体是唯一建议交给自主 agent 跑的写法——它把「验证失败就停」写成了硬约束。没有这句,agentic coding 场景下最常见的失败就是一口气改完十步,最后一步炸了,前面九步的 diff 混在一起无法定位。

进阶(自动化)

配合 Claude Code 的 /review 或 CI 单测,让计划里的每一步改完即跑测试:

# 每步改完
npm test -- --watch=false 2>&1 | tail -20
# 有问题立刻回滚
git checkout -- path/to/changed/file.ts

反例(AI 默认会写的烂重构)

「我重写了整个模块,更优雅了,顺便加了 3 个新配置项。」——违反铁律 1/4,行为可能已变、范围爆炸。 「步骤 3:把 formatUser() 抽出到 user.util.ts,保持签名与返回不变;验证:npm test user;回滚:git checkout -- src/user.ts。」

没有测试就直接改被 12 处调用的函数。 先列「12 处调用 + 现有单测覆盖 3 处」,标红未覆盖区,建议先补最小冒烟测试再动。

延伸阅读

相关对比

Aider vs Claude Code:终端 AI 编程双雄怎么选

Aider vs Claude Code 2026 选型对比:开源 BYOK 多模型 vs Anthropic 订阅长任务 Agent,从编程能力、多模型支持、价格、Git 集成、国内可用性和适合人群判断,帮你选对终端 AI 编程工具。

Aider vs Continue:终端会话派还是 IDE 自建派?2026 对比

Aider 与 Continue 2026 选型对比:两者都是开源、模型可换的路线,但 Aider 是终端里的 Git-native 会话工具,每次改动自动生成一个 commit;Continue 是 IDE 内的可配置助手,强调自定义与自托管。从 6 个维度给出明确取舍。

Aider vs Crush:CLI pair programmer vs 终端 TUI agent(2026 实测选型)

Aider vs Crush 2026 选型对比:Git 原生 AI pair programmer vs Charmbracelet 终端 TUI agent。从工作哲学、多模型、Git 集成、LSP/MCP、价格和国内可用性帮你选对终端 AI 编程工具。

Cursor vs Aider:GUI IDE 还是 CLI?2026 对比

Cursor vs Aider 2026 选型对比:GUI IDE vs Git 原生 CLI,从 Composer vs Architect 双模型、Tab 补全、多模型 BYOK、价格计费、开源与否和适合人群判断,帮开发者选对。Cursor 是闭源 VS Code fork 月费 $20,Aider 是开源 Apache-2.0 CLI 自带 API key。

Aider vs OpenCode:两个开源终端 Agent,选哪个?2026 对比

Aider 与 OpenCode 2026 选型对比:两者都是开源终端 agent、都支持换模型,但 Aider 以 Git-native 工作流与成熟的多语言支持见长,OpenCode 主打模型无关、本地优先与终端交互体验。从 6 个维度给出明确取舍建议。

Augment Code vs Cursor:企业 AI 编程怎么选?Context Engine vs AI IDE 对比

Augment Code vs Cursor 2026 选型对比:Context Engine 全仓索引的企业 AI 平台 vs SpaceX 收购的 AI IDE 天花板,从形态、Context 覆盖、长任务、价格、合规、中文支持和适合人群 8 个维度判断,帮你选对企业 AI 编程工具。

相关评测