摘要
让 AI 重构老代码,最怕的不是它改错,是它"改对了但行为变了"——测试全绿,上线才发现。实测最稳的打法不是让 AI 更小心,而是重构前先写特征测试(characterization test)把当前行为锁死,再让 AI 动手。本文给出五步可复现清单、三个坑和一个反方观点。## 为什么 AI 重构老代码忽然变"敢想"了老代码的问题是"不敢动"。几千行没人敢碰,手写特征测试要几周,重构收益遥遥无期。AI 把这个账算过来了:- snowmanlabs 实测(2026-08):特征测试让 AI 读代码、列分支、生成用例,几小时干完原来几周的活- VSCode 官方文档《Refactor code without changing behavior》(2026-10-07):先确认测试命令、记录变更前测试结果,覆盖不足先补测试再改## 翻车证据:AI 重构的"安全"是幻觉arXiv 2411.04444(180 个真实重构任务):| 指标 | 数值 ||—|—|| ChatGPT 自主识别重构机会 | 28/180 = 15.6% || 明确子类提示后成功率 | 86.7% || 方案质量可比/优于人类 | 63.6% || unsafe 比例(改功能/语法错误) | 7.4%(13/176),Gemini 6.6% |arXiv 2605.21537《Articulate but Wrong》:LLM 代码现代化自审,语义漂移39.7%、语法漂移 12.7%。它自己 review 自己,错的地方看不出来。arXiv 2608.00924(RefactorAssist):9.7% 语法/结构错误(括号配对不齐),13.7% 是"顺手加功能"——它觉得该加个变量就加了。结论:AI 重构不是不会错,是错的姿势你防不住。最阴的是语义漂移:行为悄悄变了,没人发现。## 反转:安全网是"先锁死它要改的东西"反常识操作:改老代码之前,先写测试把"当前行为"锁死——哪怕这个行为是 bug。特征测试(characterization test)由 Michael Feathers 20 年前提出:不验证"代码应该做什么",只记录"代码现在做什么"。断言现状,不是正确性。为什么 AI 时代它最有用?因为 AI 不需要"理解"代码,只需要"观察"代码——读一遍、列分支、造输入、抓输出。这恰恰是特征测试的做法,是 LLM 最擅长的事。社区套路:-Behavior-Pinning Test Before Agent Edit:改之前先跑老代码,输出存成 golden fixtures,测试不过就不许 agent 再动-cutler.sg(2026-05):AI 生成特征测试 + mutation testing 验锁,变异分数 80% 以上才解锁让 agent 改代码## 五步照着做(给数字,不给形容词)01 圈定范围。一次只让 AI 改一个 seam(接口/函数边界),别一次扫 20 个文件。Cline 做 64 文件清理靠逐文件确认防漂移(aicoderscope,2026);Aider 在 20+ 文件仓库级重构最强(repository map),但改动越大越要先锁行为。02 锁行为。让 AI 生成特征测试。输入清单照 VSCode 官方指南:默认值、边界值、非法输入、每个受影响调用方的可观察结果。核心提示词:text生成特征测试,断言这段代码【现在】的行为,不假设它应该怎样。03 验锁。mutation testing 打一遍,变异分数 <80% 就回去补测试,别急着重构。04 差分重构。让 AI 分小步改,每步一个 git 提交(Aider 默认自动 commit,天然可回滚),配--auto-test/--test-cmd每改完跑一遍测试。先问它打算怎么改,批准了再动。05 对比。重构完特征测试必须全绿。人工抽查:diff 里有没有"顺手加的优化";关键调用方输入输出是否和之前一模一样。一个函数跑通大概 1-2 小时。## 三个坑(亲测)1.别 mock 掉太多。外部依赖(DB、网络、文件)mock 到最小,不然锁的是"你想象的行为",不是真实行为。2.别让 AI"顺便优化"。prompt 明确写:只做结构变换,禁止修改任何逻辑、常量、返回值。不加这句就是递刀(13.7% 的概率)。3.别让 AI 自己验收。自审漂移 39.7% 摆在那。验收走特征测试 + 你本人抽查,不是"AI 说全绿"。## 反方:全自动重构派怎么说"我让 AI 重构就是为了省事,你还让我先写测试?“有道理:代码年轻、回归覆盖厚,特征测试是多余动作,靠现有测试兜底就行。特征测试的价值集中在老代码、覆盖薄的地方。更根本的质疑:特征测试锁的是现状,而现状可能本来就是错的。它防"行为变化”,不防"行为本来就坏"。想借重构顺手修 bug,特征测试会拦着你——你得主动决定"这次允许修哪些差异"。边界:这五步是给"行为必须不变"的重构用的(重命名、拆函数、改结构)。要改行为(加功能、修 bug)走另一条路,别混。## 小结AI 重构老代码,最怕的不是改错,是"改对了但行为变了"。特征测试不验证代码对不对,它验证代码没变。让 AI 自己验收 AI 的重构,等于让考生给自己改分。你让 AI 重构过老代码吗?遇到"测试全绿、上线翻车"了吗?评论区聊聊。—内容验真- arXiv 2411.04444:ChatGPT 识别重构机会 28/180(15.6%),细化提示 86.7%;63.6% 可比/优于人类;13/176(7.4%)unsafe,Gemini 9/137(6.6%)- arXiv 2605.21537:semantic drift 39.7%、syntactic drift 12.7%- arXiv 2608.00924:9.7% 语法/结构错误,13.7% 添加新功能或变量- VSCode 官方《Refactor code without changing behavior》2026-10-07- snowmanlabs 2026-08:特征测试 AI 数小时 vs 手写数周- cutler.sg 2026-05:mutation score 80% 门槛- aicoderscope 2026-05:Cline 64 文件逐文件确认