如何终结代码评审

2026-03-04 · 原文链接

今天公布了 AIE Europe 的第二波讲者和 AIE World’s Fair 的 CFP,并且 OpenCode 已确认会在迈阿密亮相!我们也会去 墨尔本新加坡

编者注:这是 我们的客座文章计划 的最新一篇。我们会发布那些值得认真思考的 AI 工程文章,即使我们未必完全认同——我们刚刚发布了一个 AI 评审工具,这正是那种我现在还没完全站到同一立场、但明显就在前方的观点,所以很高兴由 Ankit 来完整阐述他的论点!

当人类还在以人类速度写代码时,人类就已经跟不上代码评审了。我交流过的每个工程组织几乎都有同一个难言之隐:PR 一放就是好几天、走过场式批准、评审者因为自己也有工作要做,只能草草扫一眼 500 行 diff。

我们总把它说成质量闸门,但团队在没有逐行评审的情况下也已经发布了几十年。代码评审真正普及其实也就是 2012-2014 年前后,一位资深工程师告诉我:只不过现在已经没多少人还记得那段时间了。

而且就算有评审,系统照样会坏。我们早就学会了构建能承受失败的系统,因为我们接受了“仅靠评审并不够”这个现实。这就是为什么我们有 feature flag、分批发布和即时回滚。

我们必须放弃“把所有代码都读一遍”

根据 Faros 的数据(覆盖 1,255 个团队、超过 10,000 名开发者),高 AI 采用率团队完成任务数提升 21%,合并 PR 数提升 98%,但 PR 评审时间却增加了 91%。

现在有两件事在指数增长:变更的数量和变更的体量。我们根本不可能消化这么多代码。更糟的是,开发者持续反馈:评审 AI 生成的代码,比评审同事写的代码更费劲。结果就是团队产出更多代码,同时把更多时间耗在评审上。

靠人工代码评审,我们不可能打赢这场仗。代码评审是一个历史阶段里的审批闸门,而它已经不匹配当下工作的形状。

AI 代码评审仍然是评审

AI 代码评审工具只是在帮我们争取时间。如果代码是 AI 写的、评审也是 AI 做的,那我们为什么还需要一个漂亮的评审 UI 来展示这个过程?尽管 AI 代码评审仍有价值,但它会继续向开发流程前移。没理由在评审循环之间浪费 CI 资源、还要管理版本切换。

后置在 PR 之后的评审,在“人类写代码、需要新鲜视角”时代是合理的。但当代理写代码时,“新鲜视角”不过是另一个带着同类盲点的代理。真正有价值的是迭代回路本身,而不是把它当审批关口。

我们都知道代理并不总可靠,人类也很自然会想:我曾抓到 AI 干蠢事,所以我必须永远亲自检查。这种直觉在人工验证还可行时是对的;但在当前规模下已经不现实,而且只会越来越糟。

从评审代码,到评审意图

答案是把人类检查点上移到上游。你若觉得“不看代码”很可怕,请记住:软件开发里的检查点早就迁移过。我们已经从瀑布式签字迁移到了持续集成,也完全可以再迁一次。

Spec 驱动开发正在成为与 AI 协作的主流方式。人类应该评审的是规格、计划、约束和验收标准——而不是 500 行 diff。

在这个新范式里,Spec 才是事实来源(source of truth)。代码只是 Spec 的产物。你不需要评审代码;你要评审步骤,评审 verification rules,评审代码必须满足的契约。

Human-in-the-loop 的审批将从“你写得对不对?”转向“我们是不是在正确约束下解决正确问题?”最有价值的人类判断应发生在第一行代码生成之前,而不是之后。

通过分层建立信任

在多大程度上我们才会真正 停止读代码

如果写成规则:

代码不应由人类编写

代码不应由人类评审

LLM 并不擅长严格执行指令,它们经常偏航。它们在自我验证上也不可靠——即便代码着火了,也会一本正经告诉你“能跑”。修复方案不是让 LLM 自己去验证,而是让它写出可验证的脚本:把“判断”转成“可执行产物”。

信任必须分层。这就是 瑞士奶酪模型:没有单一闸门能挡住所有问题。你要把多个不完美过滤器叠起来,直到漏洞不再对齐。那我们还能把审批闸门放在哪?

第一层:比较多个方案

别让一个代理“必须一次做对”,而是让三个代理用不同路径尝试,再挑最优结果。让它们竞争。软件工程史上,“保留选项”的成本从未这么低。

筛选也不一定要手动。你可以按“谁通过更多验证步骤”“谁产生更小 diff”“谁没有引入新依赖”来排序输出。竞争会产生单次尝试永远给不了你的信号。

第二层:确定性护栏

工作必须有可确定性验证方式:测试、类型检查、契约验证——这些都不靠主观意见,只看事实。

与其问 LLM“这次做对了吗?”,不如定义验证步骤,产出一串可追踪的 pass/fail 证据。代理没法和失败测试讨价还价:要么满足规格,要么不满足。

这些护栏本身也应分层定义:

验证步骤应在写代码之前定义,而不是代码写完后临时编一套来“证明它没问题”。如果代理同时写代码和测试,你只是把问题搬了个位置——本质上还是在相信代理会测对东西。验证标准必须来自 Spec,而不是实现本身。

第三层:由人类定义验收标准

那人类在哪创造价值?在上游,定义“什么才算成功”。

这也是为什么行为驱动开发(BDD)重新变得重要。BDD 一直是个好主意:用自然语言写出预期行为,再把这些规格自动化成测试。但过去它没完全普及,因为你既要写规格又要写代码,感觉像额外负担。

有了代理后,方程反过来了。Spec 不是额外工作,而是核心产物。你写出:

代理去实现,BDD 框架去验证。除非失败,你根本无需读实现细节。

这才是人类最擅长的事:定义“正确”的含义,编码业务逻辑与边界情况,思考哪里会出错。代理负责把意图翻译成代码。BDD 规格变成你的验证层——可确定、可自动化、并且在第一行代码前就已定义。

由人类撰写 acceptance criteria,由机器验证。这才是真正关键的闸门。

第四层:将权限系统作为架构

这个代理可以触达什么?什么操作必须升级审批?这些应该成为架构层决策,而不是事后补丁。

多数代理框架把权限做成“全有或全无”:要么给 shell,要么不给。但权限粒度很关键。一个只是在 utility 函数里修 bug 的代理,不该能碰你的基础设施配置。一个只写测试的代理,也不该改 CI pipeline。

作用域应该尽可能窄,同时又能让代理完成有价值工作。若任务是“修复 utils/dates.py 的日期解析 bug”,那它的文件系统访问就该只限于该文件及其测试文件,而不是整个代码库,不是“src/ 和 tests/”,而是这次任务真正相关的文件。

升级触发条件同样重要。某些模式——例如改动认证逻辑、修改数据库 schema、引入新依赖——不管代理多自信,都应自动触发人工评审。

第五层:对抗式验证

职责分离:一个代理负责实现,另一个代理负责验证。它们彼此不信任,而这正是设计目的。

这其实是老模式了——这就是为什么 QA 团队不该向工程经理汇报,也为什么写代码的人不该是唯一评审者。

在代理体系里,你可以把这件事做成架构约束。编码代理不知道验证代理会检查什么;验证代理也无权修改代码来让自己“更容易通过”。它们应被设计成对抗关系。

还可以更进一步:加入第三个代理,专门尝试攻击第一个代理构建的内容,定向覆盖边界条件和故障模式。红队 vs 蓝队——但自动化,并且对每次变更都运行。

结论:“好代码”的定义正在变化

代理系统的激励很简单:给定任务,我能不能完成?我能不能让下达任务的人满意?代理的成功天然并不由长期正确性或业务要求驱动。

把这些约束编码进去,是我们的工作。

当代码由代理生成、由代理阅读时,“好代码”的样子会更加标准化。面对新代码库时,你需要给的指令会更少,因为默认模式会越来越一致。

未来是:快速发布、全量观测、更快回滚。

不是:慢慢评审、照样漏 bug、再去线上救火。

我们不可能比机器读得更快。我们需要在更上游的决策层,想得比它们更好。

归根结底,如果代理已经能很好处理代码,那么我们“能不能读懂它”,还重要吗?

Ankit JainAviator 的创始人兼 CEO,他正在构建面向 AI 原生工程团队的基础设施。Aviator 平台帮助现代组织在保持高工程标准的同时提升 AI 采用率。