采用 AI 编程工具后代码速度提升但缺陷率反而上升,审查压力成为团队真实瓶颈;深入揭示 AI 编程的工程挑战。
有一种失败模式,我已经见过足够多次,可以把它称为一种规律,而不再只是个别案例。它通常是这样发生的。
一个团队开始认真采用 AI 辅助工具。开发速度明显提升——图表上的数据清清楚楚,而且这种增长持续了大约两个季度。所有人都很满意。随后,事故率开始上升,但人们花了长得令人尴尬的时间,才确认两者之间的关系,因为这些事故分散在各处:一个从未添加的 null 检查、一项放错层级的授权检查、一条在一万行数据时没有问题但缺少索引的查询。
根本原因不在工具本身,而在于代码生成吞吐量提高了,代码理解吞吐量却没有提升,也没有人为这个新的约束调整流程。
2023 年以前的工作流有一个非常有用的特性:没有人专门设计它,但所有人都依赖它——编写代码的人理解这些代码,因为编写本身就是他们理解代码的过程。代码审查是在已有第一判断的基础上提供第二意见。
对于生成的代码,这一特性已经消失。如今,代码审查往往是第一次有人真正建立起“这段代码究竟做了什么”的心智模型。这在本质上是一项完全不同的任务,而且审查每一行代码所需的时间更长,而不是更短。
与此同时,进入审查环节的代码量却增加了。两条曲线正朝着相反的方向发展。
可观察到的症状非常一致:pull request 越来越大,审查延迟不断增加,审批质量在队列压力下逐渐下降;而最重要的是,审查者开始根据代码看起来是否合理进行模式匹配,而不再真正验证其行为。生成的代码尤其擅长营造“看起来没问题”的感觉:命名正确、结构合理、错误处理也貌似可信。但它会在那些需要了解你的系统才能正确处理的地方出错,例如存在于另一个服务中的不变量、某张表之所以没有索引的原因,或者必须在 fetch 之前而不是之后执行的 auth 检查。
下面是六项改进措施,大致按照投入回报率排序。
这是杠杆效应最高的一项改进。生成式工具让大型 PR 变得轻而易举,却没有让它们更容易审查。设置硬性上限——可以从 400 行变更开始,不计 lockfile 和生成的 schema——会迫使开发者在拆分成本还很低的时候就完成拆分。
通过 CI 强制执行,而不是依赖团队文化。每当遇到截止日期的压力,文化规范都会败下阵来。
在 PR 中增加一个单行字段:代码主要由 AI 生成、主要由人工编写,还是二者混合?
这听起来像官僚流程,但实际上并非如此。它会改变审查者的工作方式。对于一位了解系统的同事手写的代码,审查者会带着一种先验判断;而生成的代码并不具备同样的先验可信度。只有知道自己正在审查哪一种代码,审查者才能正确校准判断。如果没有这个信号,他们就会对两者应用相同的先验判断,而这必然会在某个方向上出错。
它还能产生数据。六个月后,你可以在自己的代码库中分析代码来源与缺陷率之间的相关性,而不必再拿别人的博客文章争论。
制定一份明确而简短的清单。不同系统的具体内容会有所差异,但基本框架通常是一致的:
身份认证和授权逻辑
加密操作与密钥处理
任何涉及资金、计费或账本状态的内容
对承载生产流量的数据表执行 schema migration
访问控制策略
数据删除与保留的级联逻辑
并发原语与锁机制
这并不是因为 AI 无法生成这些代码,而是因为在这些领域,“看起来合理但实际上错误”的代价最高,也最不容易被测试发现。这条规则的真正目的,是在潜在影响范围最大的地方,强制要求由人类掌握完整的心智模型。
生成的单元测试存在一个系统性弱点:它们往往只测试刚刚生成的实现,包括实现本身的错误。如果一个生成的函数存在 off-by-one 错误,而生成的测试又断言了这个错误行为,那么两者会构成一组完全自洽的代码,并且测试可以顺利通过。
基于属性的测试——声明独立于具体实现的不变量。例如:“序列化后再反序列化,应得到相等的值。”“执行任意操作序列后,账本仍然保持平衡。”
针对真实依赖项的集成测试——使用真实数据库、真实队列,并在容器中运行。Mock 编码的是假设,而生成的 Mock 编码的是由 AI 生成的假设。
服务边界处的契约测试——代价高昂的故障真正发生的地方。
关键路径上的 mutation testing——这是区分“真正验证行为的测试”与“仅仅执行代码行的测试”的唯一可靠方式。
代码覆盖率百分比一直都是一个很弱的信号。在生成测试的时代,它几乎已经毫无意义,因为现在可以轻而易举地制造覆盖率。
审查者的注意力如今是整个流水线中最稀缺的资源,因此必须有意识地使用它。把机器更擅长完成的事情全部交给工具:
以最高严格级别执行静态分析和类型检查
执行依赖项与供应链扫描,包括检查 AI 助手建议的所有依赖项——AI 幻觉出一个并不存在的包名,之后攻击者注册同名包,这是一种真实存在的攻击模式
在 pre-commit hook 中执行 secret scanning,而不只是在 CI 中执行
检查热点路径上的性能回退
自动检测生成代码中的常见坏味道:吞掉异常、无限重试、N+1 查询以及缺少分页
每自动化一个项目,就能把注意力还给那些只有人类才能检查的问题——这段代码对于当前这个系统而言是否正确。
生成的代码通常在局部看起来合理,但从全局来看却值得怀疑。它不了解你的服务边界、现有工具,也不知道你在两年前出于充分理由刻意避开的某种抽象。
将架构审查和逐行代码审查分开会有所帮助,因为这两个问题需要不同的上下文,也需要不同的审查者。“这段代码究竟该不该放在这里?”与“这个循环是否正确?”是两个不同的问题。如果要求审查者同时回答它们,其中一个问题获得的关注就会少于实际需要。
因为这直接关系到项目如何定价。
当前工具确实能够压缩的工作包括:样板代码、CRUD、API client、测试脚手架、migration、第一版接口、文档,以及熟悉陌生代码。这些收益真实、可衡量,并且在企业级项目的总工作量中占据具有实际意义的一小部分。
完全没有被压缩的工作包括:理解一套没有文档的业务流程、集成一个原作者已经离职的遗留系统、解决部门之间的数据模型争议、安全架构、负载行为、法规解释以及利益相关者之间的协调。这些工作才占据主导地位。
新增的工作包括:随使用量增长的 inference 运营成本、评估基础设施、drift monitoring,以及上文所述的代码审查负担。
因此,如果供应商声称“因为有 AI”,价格可以降低 50%,那只是在描述一种幻想。真实的降幅要小得多,而且只有调整了流程的团队才能获得。没有调整流程的团队并没有节省成本;他们只是把成本推迟到了一个从未有人预测过的维护预算中。
如果你正在评估一个团队——无论是内部团队还是外部团队——请问两个问题。
你们用什么标准判断哪些内容不得生成?如果对方能提供书面答案,说明他们认真考虑过潜在影响范围。如果没有答案,就意味着他们把系统的每一个部分都当成同样适合自动化的内容,而在我参与过的任何系统中,这都不符合事实。
你们的代码审查流程发生了哪些变化?“没有变化”本身就是一个完整而令人担忧的答案。代码生成吞吐量大幅提高。如果下游流程没有进行任何调整,那么压力就会被队列吸收,而队列吸收压力的方式不是抱怨,而是降低质量。
关于美国交付模式、真实费率、合规成本、合同结构及预算的完整指南:美国定制软件开发服务:2026 年成本与供应商指南。
因为代码审查往往是第一次有人真正建立起“这段代码究竟做了什么”的心智模型。过去,作者会在编写过程中建立这种理解,而审查是在已有判断的基础上提供第二意见。从零开始建立心智模型,需要为每一行代码投入更多时间。
身份认证与授权、加密操作、任何涉及资金或账本状态的内容、生产数据表上的 migration、访问控制策略、删除与保留的级联逻辑,以及并发原语。在这些领域,“看起来合理但实际上错误”的代价最高,也最不容易被测试发现。
有一定作用。它们往往只测试刚刚生成的实现,包括实现中的 bug,最终形成一组能够通过测试的自洽代码。基于属性的测试、针对真实依赖项的集成测试、契约测试,以及关键路径上的 mutation testing,都是可靠得多的信号。
它的意义比以往任何时候都更小。现在可以轻而易举地制造覆盖率,因此较高的百分比只能说明代码行被执行过,并不能说明其行为经过了验证。关键路径上的 mutation testing 是一种切实可行的替代方案。
通过 CI 强制限制 pull request 的大小。生成式工具让大型 PR 变得轻而易举,却没有让它们更容易审查,而审查质量会随着 PR 规模扩大而急剧下降。关于 PR 大小的文化规范会输给截止日期的压力,CI 则不会。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。