§ Essay
如何避免 AI 越改越乱?
和 AI 一起写代码,最大的风险不是写不出来,而是越改越乱。用 TDD 用例当唯一 Spec、拷问式提问拉齐认知、Issue 式整体分析修 Bug、重构节奏防止测试腐化,这四条规则对抗 AI 协作时代的项目腐烂。
和 AI 一起写代码,最大的风险不是写不出来,而是越改越乱。下面这四条规则,是从实践中沉淀下来的对策。
1. 用 TDD 用例代替文档,作为唯一的 Spec
可执行的测试比静态文档可靠 —— 也就是常说的活文档(Living Documentation)。
文档为什么会失效?
| 原因 | 说明 |
|---|---|
| 描述不准确 | 自然语言天生有歧义,写的时候可能就没想清楚 |
| 描述过时 | 代码改了,文档忘了同步,变成”僵尸文档” |
| AI 上下文问题 | 长文档被上下文压缩后,AI 会”忘掉”关键细节,甚至产生注意力幻觉 |
为什么 TDD 用例是更好的 Spec?
| 维度 | 文档 | TDD 用例 |
|---|---|---|
| 可执行 | 静态描述,跑不起来 | 自动运行验证 |
| 同步性 | 易过时 | 失败即过时,骗不了人 |
| 歧义 | 自然语言模糊 | 代码精确无歧义 |
| AI 友好 | 上下文压缩可能丢信息 | 用例 = 标准 harness,幻觉率极低 |
例子:
- 文档写法:用户登录功能支持邮箱登录。
- 测试写法:输入邮箱 + 正确密码,期望返回登录成功;输入错误密码,期望返回
401。AI 不小心把登录逻辑改成手机号时,测试会直接报错,它就能立刻自我纠错。
一个容易踩的坑:测试只描述”What”,不描述”How”
测试关心的是”做了什么”,不是”怎么做”。换句话说:区分事实(业务行为)和实现(内部细节),只绑定前者。
打个比方:验证”快递送到了吗”,应该看包裹在不在门口、完不完整;而不是跟踪快递员走了哪条路、用了什么交通工具、中途停了几次。快递员换电动车、改路线,快递还是那个快递。但如果测试在追踪路线,换路就会导致全部测试失败,逼着你去”修测试”。
这对 AI 协作意味着:
| 后果 | 说明 |
|---|---|
| 重构即崩塌 | AI 改个内部函数名 / 调用顺序,所有测试瞬间失败 |
| AI 陷入”修测试”泥潭 | AI 误以为测试是真理,转去迁就测试而不是修逻辑 |
| 幻觉率飙升 | AI 编造”补丁代码”让旧 mock 重新匹配,反而引入新 Bug |
记住一句话: 测试是契约(Contract),不是说明书(Instruction) —— 它规定”应该发生什么”,不规定”必须怎么做”。
2. 用”拷问 Skill”做前期认知拉齐
编码前先把问题想透,用结构化提问把需求、设计和边界”拷问”清楚。这是 Matt Pocock(TypeScript 领域专家)提倡的方法,通常封装成一个 AI Skill(提示词模板):写代码前,用一系列尖锐、结构化的提问,把模糊的想法逼成清晰的规范。
为什么这比编码本身更重要?
| 理由 | 说明 |
|---|---|
| 方向错误是最大的浪费 | 编码后期才发现理解偏差,返工成本极高 |
| AI 编码快,但思考不能省 | 你自己认知模糊,AI 只会更快地生成一堆漂亮的废品 |
| 拷问过程 = 共识对齐 | 强迫产品、开发、AI 用同一套术语和逻辑理解问题 |
一句话: 用人类的严谨思考,为 AI 的快速执行铺路 —— 把需求从”散文”变成”合同”。
3. 用”Issue 式整体分析”修 Bug,拒绝饮鸩止渴式 Hotfix
把 Bug 当作一个小需求来修:先分析、设计、规划,而不是匆忙打补丁。
Hotfix 的危害:
- AI 倾向最小改动掩耳盗铃:加
if、吞try-catch、把简单逻辑改得绕来绕去。 - 系统腐化:补丁越积越多 → 兼容代码爆棚 → 熵增到不可维护 → 彻底救不回来。
正确的修法,像处理 Issue 一样:
1. 统一管理 所有 Bug 进 Issue 系统,不靠人脑记
2. 整体分析 根因是什么?影响范围?是否暴露设计缺陷?
3. 拉齐认知 原需求没覆盖?还是设计有漏洞?明确"正确行为"
4. 系统化重构 让 Bug"不存在",而非"被掩盖"
修 Bug 不是在贴创可贴,而是在修复滋生 Bug 的源头 —— 与其外科手术式地切除,不如免疫系统式地增强。
测试先行:每个 Bug 修复必须附带缺失的测试用例
修 Bug 不是结束,而是补全 Spec 的开始:
1. Bug 出现 → 说明至少有一个业务场景没被现有 Spec 覆盖
2. 根因分析 → 找到缺失的场景
3. 先补测试 → 写一个"如果以前有这个测试,Bug 就不会发生"的用例
4. 再修代码 → 让新测试通过,同时保证老测试全绿
5. 回顾 → 这个测试该归到哪?要不要重构测试结构?
收益: 同一个坑不会踩两次,测试套件随 Bug 修复越来越健壮 —— 这才是真正的”免疫系统增强”。
4. 用”重构节奏”防止测试自身腐化
TDD 用例不是越多越好,测试套件本身也需要定期维护,否则会从资产变成负债。
测试文件为什么会腐化?
| 原因 | 说明 |
|---|---|
| 场景堆积 | Bug 修复不断追加用例,文件越来越臃肿 |
| 僵尸测试 | 被 skip / only 的用例长期不清理 |
| 命名漂移 | describe / it 的描述已不能准确反映业务语义 |
| 反馈变慢 | 测试运行太久,拖慢 AI 反馈循环,TDD 的核心价值被稀释 |
卫生检查清单
建议每两周或每个迭代末做一次轻量扫描:
- 有没有重复的测试场景?
- 有没有永远不跑、被
skip的测试? -
describe/it描述还能准确反映业务吗? - 运行时间会不会拖慢 AI 反馈?
节奏建议: 每两周花 30 分钟,让 AI 扫一遍测试套件 —— 重复、命名不规范、跑太慢的测试,AI 很擅长找出来。
一句话总结
可执行测试当事实来源,前置拷问做认知拉齐,Issue 式分析修 Bug,重构节奏维持测试健康 —— 这四条是 AI 协作时代对抗项目腐烂的根本对策。