我用 AI 写了 8 万行代码,然后花了三个月还债:一次 Vibe Coding 技术债审计实录

📅 2026/4/26 ✍️ 小文 📖 约 1 分钟

Vibe Coding 让原型速度提升 5 倍,但代价被严重低估。本文是一个真实项目的技术债审计报告:8 万行 AI 生成代码里查出了什么、哪些债必须马上还、哪些可以永远不还,以及一套可复用的「AI 代码体检清单」。

去年十一月,我们用一个周末加两个模型账号,做完了过去要两个月的产品原型。团队当时很兴奋,我甚至在周报里写了「开发效率提升 5 倍」。三个月后,这套代码变成了 8 万行、没人敢动的黑箱,新功能开发速度反而慢于传统方式。这篇文章就是那次救火行动的完整审计报告。

一、先说结论:债不是均匀分布的

我们对 8 万行代码做了分类统计,AI 生成代码的问题集中度极高:

问题类型占比危害等级修复成本
重复实现(同一逻辑写了 4-6 遍)31%中低
缺失错误处理与边界判断22%高中
幻觉依赖(引用了不存在或已废弃的 API)12%极高高
过度抽象(为一次性需求建了完整分层)18%低低
隐性全局状态与竞态9%极高极高
测试形同虚设(断言永远为真)8%高中

注意最右边两列的组合关系。真正杀死项目进度的不是重复代码,而是那 9% 的隐性状态问题——它们只占代码量的一成,却吃掉了我们救火时间的六成。

二、三类必须立刻还的债

1. 幻觉依赖

AI 写代码时最危险的时刻,不是它写错逻辑,而是它自信地调用一个不存在的函数。我们的审计脚本很简单:把所有 import 和包调用抽出来,逐个对着实际安装的版本做符号存在性校验。结果发现 14 处调用了「某 SDK 未来版本才会有的方法」,还有 6 处引用了只在博客文章里见过的配置项。这些代码平时不执行,一旦踩到分支就抛异常。

2. 隐性全局状态

这是最贵的。AI 很爱用模块级的可变变量做「缓存」,在多账号登录场景下,两个请求共享了同一个状态对象,导致 A 用户的配置泄漏给了 B 用户。这类 bug 在本地单人测试时永远不会出现。

检测方法:对所有模块顶层的赋值语句做人工过一遍,凡是可变对象(字典、列表、类实例)就标记。我们一共标了 37 处,其中 11 处是真问题。

3. 假测试

AI 生成的测试有个显著特征:它倾向于测试自己刚写的实现,而不是需求。断言写成了 assert result == function_itself(x),这种测试永远通过,也永远没价值。我们的判据是:把被测函数的实现注释掉,看测试会不会红。37 个测试里,有 21 个照样绿。

三、可以永远不还的债

这是审计中最重要的认知转变。以下这些,我们决定不修:

  • 重复代码:用代码压缩工具统一格式化后,重复的部分并没有产生维护成本——因为它们是稳定的、不变化的。
  • 过度抽象:留着不碍事,删掉反而引入风险。
  • 命名难看、注释缺失:让 AI 自己补一遍注释即可,成本几乎为零。

真正需要还的只有两类:会引发错误的和会阻止理解的。其他都是洁癖。

四、可复用的 AI 代码体检清单

我们把这套流程固化成了一个脚本,每次 AI 大规模产出后跑一遍,十分钟出报告:

  1. 依赖校验:所有第三方符号是否在当前版本真实存在
  2. 假测试扫描:注释实现看测试是否仍为绿
  3. 顶层可变状态枚举:自动列出所有模块级可变对象
  4. 错误路径覆盖:统计 try 块数量与网络调用数量的比值,低于 0.8 就告警
  5. 幽灵分支:AI 常写 if config.get("xxx"),但配置文件里根本没这个键,全部列出来

五、三个月后的复盘

还债完成后,这套代码的迭代速度回到了正常水平——不是 5 倍,是 1.3 倍。这才是 Vibe Coding 的真实收益。

但那 1.3 倍依然值得。因为它的价值不在「省了工时」,而在把「要不要做这个产品」的决策成本降到了接近零。我们现在可以用两天验证一个想法,失败了直接扔。这种情况下,8 万行代码的技术债不算债,算学费。

关键区别是:原型阶段可以不还债,产品阶段必须还。 而我们那次犯的错,是忘了在两者之间划一条线。

📤 分享到