AI 生成代码已近乎零成本,但评审仍是人力密集环节;METR 实验显示开发者用 AI 效率自我感知提升 20%,实际却慢 19%;团队级数据同样指向评审是瓶颈。
打字几乎不花钱了。理解代码不是,而交付就卡在这里。
我每天用 Claude Code 做重构、生成测试和评审。它擅长生成 diff,但不擅长生成一个充分理解 diff、能为之署名的人。
我认为现在决定团队交付速度的是评审容量,而非生成速度。技术负责人应该像规划构建容量一样规划评审容量。
没有人因为打字快而交付更快。交付的慢在读、在判断、在检查、在达成共识。
AI 工具移除了一步本来就廉价的步骤,却让昂贵的步骤变得更频繁。每天收到的 diff 更多了,而每一个仍需要有人去读。
有两组数据一直让我反复思考。
METR 用经验丰富的开源开发者在他们自己的仓库里做了一项随机对照试验。他们用 AI 时慢了 19%,但他们相信 AI 让他们快了 20%。
这两组数字之间的差距才是我关注的。如果干活的人都感受不到减速,团队也不会注意到,直到仪表盘显示了。
团队层面的数据指向同样的方向。高 AI 采用率的团队合并的 PR 多了 98%,评审时间增加了 91%,而 DORA 交付指标原地踏步。
个人产出上升,代码质量下降,而组织层面的交付没有动弹。工作在评审者面前堆积,而评审者是 AI 唯一没有倍增的资源。
当一位同事写了改动,我可以根据作者推断很多东西。我知道他们通常哪里做得好、哪里会偷懒、他们对系统的哪些部分理解最深。
生成代码没有这些。它流畅、格式一致,所以看起来同样可信,包括那些出错的地方。
作者也处于更弱势的位置。如果 diff 来自一个 prompt,他们可能没有建立起每行为什么在那里的模型。那么评审者是第一个需要建立这个模型的人,而这才是慢的部分。
所以我在团队里的第一条规则是:作者必须能够解释 PR 里的每一行代码。如果不能,这个 PR 还没准备好给评审者。
最强的反对意见是这个问题是暂时的。如果模型能写代码,模型也能评审,瓶颈就消失了。
我确实用 AI 做评审,它有帮助。它在人花时间之前就抓到了机械性问题、不一致的命名、缺失的错误处理和被遗忘的边界情况。
但它没有移除瓶颈,原因有两个。同模型家族的评审者共享生成者的许多盲点,所以他们的同意看起来比实际说服力更弱。
另一个原因是问责制。团队里必须有人拥有生产环境里的这个变更,而那个人必须理解它。模型的批准不能给人类那种理解。
所以我把 AI 评审当作一个过滤器,缩小人类需要阅读的范围,但人类仍然要读。
如果评审时间是稀缺资源,它应该只流向需要判断的地方。机器能检查的一切应该在人打开 PR 之前就检查掉。
name: pr-gate
on:
pull_request:
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm test
这很无聊,但是有意为之。评审者永远不应该是发现类型检查失败的那个人。
架构也有帮助。在我目前雇主的网格应用中,后端遵循六边形布局。核心域的变更需要慢而仔细的评审。适配器的变更,比如 REST 映射或持久化查询,只需要对实现的端口做一个轻量级通过。
这给了评审者一张注意力分配地图。没有边界,每个生成的 diff 都在所有地方要求同等的怀疑。
最便宜的评审发生在代码存在之前。当我让 agent 改变行为时,我希望预期行为被人类编写或至少仔细阅读过的测试锁定。
import { describe, expect, it } from '@jest/globals';
import { nextStep, defaultPolicy } from './retry-policy';
describe('nextStep', () => {
it('retries while attempts remain', () => {
const attempt = defaultPolicy.maxAttempts - 1;
expect(nextStep(defaultPolicy, attempt)).toBe('retry');
});
it('dead-letters once attempts are exhausted', () => {
const attempt = defaultPolicy.maxAttempts;
expect(nextStep(defaultPolicy, attempt)).toBe('dead-letter');
});
});
我在基于 RabbitMQ 的集成中关心这类规则,重试和死信行为决定了长时间计算能否熬过一个问题多发的夜晚。
读两个小测试远比为推断同样规则而看一个大 diff 便宜。如果测试正确且通过,评审者可以浏览实现看结构,而不是重新推导意图。
我还保持 PR 小规模,要求生成的重构按关注点拆分。一个混合了重命名、行为变更和新测试文件的大 diff 是你能交给评审者最贵的东西。
大多数团队为构建做预算,把评审当作间隙发生的事情。当写代码是慢步骤时这还能运作。当 diff 到达速度快过人能读的速度时,这就崩了。
在一个五人的团队里,评审是一个共享的注意力池,而且它是有限的。我明确地围绕它做计划。
我限制一个人能同时打开多少个 PR,这样生成就不能跑在阅读前面。我们在讨论 sprint 容量时把评审算作真实的工作。我问一个功能评审起来要花多少成本,而不只是它生产起来要花多少。
我还关注交付而非产出。合并的 PR 更多意义不大,如果描述给用户带来价值的指标还停留在原地。
生成现在很便宜。理解是你仍然要为之付费的,所以为它做预算吧。