重构 Prompt:18 个让 AI 重构更安全的模板

18 个可直接复制的 Prompt,规划、执行、验证 AI 重构——模块抽取、重命名、async 迁移、god 函数拆分,不弄崩行为。

重构翻车通常因为:太大、不可测、悄悄改了行为。下面这 18 个 Prompt 强制更小、可验证的步骤——模型能一次做完,人能不通读整个文件就 review。

这套 Prompt 主要解决什么问题

重构的唯一职责:改结构、不改行为。所以 Prompt 必须 (a) 指出要改的单元,(b) 列出必须保留的不变量,(c) 圈定范围避免模型”顺手改一下”,(d) 强制先给计划或 diff 再动手。

这篇适合谁

用 Claude Code、Cursor、Codex 推大重构的资深工程师;整治遗留模式的 tech lead;在迁移代码范式(callback → async、class → hook、JS → TS)的独立开发者;上线前抽热点函数的 on-call。

什么时候不建议用

编辑器 1 秒就能搞定的单行重命名——别用,Prompt 成本比工作量大。完全没有测试——重构没有安全网就成了重写,这些模板默认有验证环节。别把重构和加功能塞进同一个 Prompt——模型会偷偷把功能塞进”重构”diff 里。

Prompt 结构公式

一个重构 Prompt 应包含 6 个要素:

  • 目标单元:具体某个函数 / 文件 / 模块 / 模式——不要”整个代码库”。
  • 目标形状:改完是什么样——“抽到模块 X”、“转 async/await”、“拆到每个函数 ≤80 行”。
  • 不变量:行为保留、公开 API 保留、测试还绿、不引入新依赖。
  • 范围围栏:模型可改的文件列表;其他都是只读上下文。
  • 先计划后 diff:先输出迁移计划,等确认,再 apply。
  • 验证钩子:跑哪些测试、过哪条 lint、type check 必须干净。

这套 Prompt 适合用在哪

  • 模块抽取与 API 表面整理
  • 严格类型迁移(TypeScript / mypy / Sorbet)
  • 模式现代化(callback → async、class → hook)
  • 拆 god 函数 / god 文件
  • 把 one-off helper 换成 stdlib
  • 跨多调用点的重命名
  • Agent 模式重构任务(Claude Code / Cursor 的 agent 模式)

18 个可直接复制的 Prompt 模板

1. 抽取模块

用在一个文件长出两种职责、其中一种应该搬出去。

你是重构 agent。把 {functionality} 从 {source-file} 抽到新模块 {target-path}。约束:source-file 公开 API 保持、所有测试还过、不改行为。输出:(1) 迁移计划编号列表,(2) 新文件内容,(3) source-file 的最小补丁——重新导出被搬走的符号。不动列表外文件。

变量: {functionality}{source-file}{target-path}

Tip: 显式要求 re-export shim,这样老 import 在同一 PR 里不会断。

2. 安全重命名

把 {old-name} 重命名为 {new-name}(全仓库)。步骤:(1) 列每处使用的 file:line,(2) 给一个代表性 call site 的 before/after,(3) 对任何含义现在不对的调用方变量(例如以旧名命名的局部变量)建议保语义重命名。不要 find-and-replace;给出每文件 diff,然后停下等我 review。

3. 内联过度抽象的 helper

函数 {name} 只被使用一次。请在调用点内联。输出:两个文件的 diff、一句话确认行为完全一致、我应该重跑哪条测试命令。

4. 继承换成组合

下面是一个类层级。请给出基于组合的重构方案。输出:(a) 新组件/策略接口,(b) 每个类的迁移计划,(c) 哪些测试需要改、为什么,(d) 应用变更的顺序——保证每一步 build 都绿。

层级:{paste}

5. callback → async/await

下面是 callback-based 代码。转 async/await。保留错误语义(rejected promise 错误形状必须和原 callback 收到的一致)。标出任何行为微差(例如并行变串行)。输出 diff 加一节"行为差异",列每个可能改变语义的地方。

代码:{paste}

6. 严格类型迁移

把 {file} 从松类型迁到严类型({source-config} → {target-config})。第 1 遍:识别所有隐式 any / unknown cast / 缺返回类型。第 2 遍:先修最有把握的;不确定的类型先留 `// TODO type`。不改运行时行为。

文件:{paste}

7. 拆 god 函数

函数 {name} 200+ 行。请拆成更小函数。每个新函数:名、单句职责描述、签名。不改行为。按可以一段一段独立提交(每个 commit 都绿)的顺序输出 diff。

函数:{paste}

8. 自制 util 换成 stdlib / 库

下面是自制代码。识别在重复造 stdlib 或常用库轮子的函数。每处匹配:行号范围、建议替换(含 import 路径)、删除前我应该验证的 1 个 edge case。

代码:{paste}

9. 边界重构——把 I/O 推到边缘

函数 {name} 把 I/O(网络 / 磁盘 / DB)和纯逻辑混在一起。请重构成把 I/O 推到边缘:抽一个纯内层函数(输入是已取到的数据,输出是结果);外层只留薄薄的 I/O 壳。输出:新签名、一句话说明现在哪些原本不可测的部分变可测了。

10. 删死代码

审计 {scope} 的死代码:未导出且无内部调用的符号、导出但下游零使用的符号、值已写死的 feature flag、永远不会执行的分支。每个:file:line、判定它是死代码的证据、建议删除步骤。跳过任何反射 / 动态调用(字符串 key 访问)。

11. Hooks 重构(React)——抽自定义 hook

组件 {name} 把 state、effect、render 混在一起。把数据层抽到自定义 hook `use{Name}`,返回 `{ data, loading, error, refetch }`。组件留作纯 render。输出新 hook 文件、组件 diff、每个关注点 1 个测试思路。

12. 数据库查询重构——把 N+1 收成单次拉取

下面是一段在循环里每次发查询的代码路径。请重构成单次批量拉取。约束:结果顺序保留、错误语义保留(一处失败仍以一个错误浮出)、不引入新 ORM 特性。输出:diff 加一段说明现在依赖哪个 DB 索引。

代码:{paste}

13. promise 链转 async/await

把下面的 promise 链转 async/await。完整保留 `.catch` 语义——每条 reject 路径都还要被处理。如果删掉某个 `.then` 分支,请用 1 行说明理由。输出 side-by-side before/after。

代码:{paste}

14. 两步弃用重构

弃用 {api-name}。第 1 步(本 PR):新 API 与老 API 并存、给老 API 标 @deprecated、把一个代表性 call site 切到新 API 作为证据。第 2 步(不在本 PR):迁移其余 call site。输出:剩余 call site 的迁移顺序——最容易的先。

15. 跨文件常量合并

{constant} 在 N 个文件里重复(粘贴)。请合并到单一来源。输出:规范化的文件 / 位置、每个消费方的 diff、一项检查(合并前每个原位置的值都一致)。

文件:{paste}

16. Agent 模式重构简报(Claude Code / Cursor agent)

你有仓库访问权限。把 {pattern} → {new-pattern} 重构跨 {scope} 应用。规则:(1) 每个 commit 一个文件,(2) 每个 commit 后测试必须过,(3) 公开 API 不变,(4) 遇到模糊就停下问我——不要猜。先按 commit 顺序列出你打算改的文件,等我说"go"。

17. 行为保留测试生成

下面是我即将重构的函数。动手前,请写 6 个特征化测试锁定当前行为——其中 2 个测覆盖现有测试漏掉的 edge case。重构后我会重跑,必须仍过。

函数:{paste}

18. 重构 diff sanity check

下面是我即将以"纯重构"合并的 diff。请审计:任何可能改变行为的变化——控制流、错误处理、返回形状、异常类型、null 处理、顺序。每处嫌疑:file:line、潜在差异、用什么测试能确认。

Diff:{paste}

容易踩的坑

  • 大爆炸重构无验证。 Prompt 没要求先写测试;模型返回 400 行,你不知道哪里坏了。
  • 行为改动偷偷塞进重构。 模型在重构时”顺手”修了 bug——diff 现在混着两种意图,review 时间翻 3 倍。
  • 重命名跳过搜全使用。 一个文件改完;其他地方某个字符串 key 引用还指向旧名,运行时悄悄坏。
  • 重构和加功能塞同一个 Prompt。 模型返回重构 + 你没要的新选项。一个 Prompt 一个意图。
  • 没有范围围栏。 没显式”不要碰 X”,模型会扩散到相邻文件,因为它看到不喜欢的东西。
  • 没有”先计划后 diff”步骤。 直接出补丁;apply 后才发现计划错了。
  • 轻信模型的”行为没变”声明。 永远跑模板 17 的特征化测试——模型在这一点上错得意外频繁。

下一步怎么继续提升

  • 每个 Prompt 锁定一个重构模式——抽取、重命名、内联。混在一起就稀释信号。
  • 在 agent 模式里强制每个 commit 一个文件。回滚更容易、review 更容易、两天后 bisect 更容易。
  • diff sanity check(模板 18)作为对模型自身输出的第二遍 pass。
  • 跨多文件迁移时,先让 AI 按风险给文件排序(调用方最多、测试最多),低风险先做建立信心。
  • 重构 Prompt 永远配特征化测试(模板 17)。变更前 pin 住的测试才说明实际改动。
  • 范围围栏让模型守规矩:“可改文件:A、B、C。其他只读。“放第一行,agent 模式也会守。
  • 重构后,让模型用 5 个 bullet 把 diff 反向解释给你。如果它无法干净总结,说明重构做太多了。

FAQ

  • 重构 Prompt 和代码 review Prompt 有什么区别? 重构改代码、review 评估代码。用代码 review Prompt审重构 Prompt 产出的 diff。
  • 为什么模型重构时一直在加功能? 约束漂移。在 Prompt 末尾加一句:“如果重构中发现 bug 或缺失功能,列到 NOTES 一节,但不要改代码。” 这样意图就隔离了。
  • 一个 Prompt 能做多大的重构? 大约一个函数、一个文件、或跨 ≤5 个文件的同一模式。再大就拆——模型会丢失不变量,你 review 时也会。
  • agent 模式可以让它自动 apply 重构吗? 仅在每 commit 一个文件 + CI 跑测试的前提下。否则两天后某处坏了,你失去 bisect 能力。
  • AI 说”行为没变”但我的测试挂了怎么办? 信测试。让模型把自己的输出和原文 diff,找语义实际偏移的那一行——通常它能找出来。
  • 重构还是重写? 文件 >50% 改动 = 重写。这种情况用迁移规划 Prompt,不是重构 Prompt。

相关阅读

标签: #Prompt #AI 编程 #重构