> ## Content Index
> Fetch the complete content index at: https://andybase.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# 当代码不再稀缺 - 05
- URL: https://andybase.com/dang-dai-ma-bu-zai-xi-que-05/
- Published: 2026-07-29T02:38:26.000Z
- Updated: 2026-07-29T02:39:28.000Z
- Author: andy

## Code review 没有过时，但我们可能 review 错了对象

> **AI can produce a diff. Review decides whether the team is willing to own the change.**  
> AI会产出代码，但是团队应该决定是否拥有这个改变

上一篇：[AI 时代还需要 Estimate 吗？](https://andybase.com/dang-dai-ma-bu-zai-xi-que-04/)

床位系统那个 bug 暴露以后，我反复想过一个问题：

> 我们明明做了 code review，为什么还是没有发现这个bug？

实现并不离谱。代码在判断查询时刻是否落在预约区间内，局部逻辑说得通，边界也长得像正常的时间处理。

只是业务真正问的是“这一天是否已经被占用”，代码回答的却是“当前这一秒是否落在区间”。

我们不是没看代码。我们看了一个错误问题的正确答案。

这件事让我意识到，AI 时代关于 code review 最危险的讨论，不是“以后还要不要 review”，而是：

> **我们到底在 review 什么？**

## 旧 Review Contract 有一个隐藏前提

过去的 code review，大多建立在一条没有写出来的 assumption 上：

```text
Author 接到需求
→ Author 理解问题
→ Author 亲手实现
→ Diff 是这段理解的主要表达
→ Reviewer 通过阅读 diff 判断实现是否合理

```

这条链当然有时也会断。工程师从来不会因为亲手敲键盘就自动获得业务知识。

但至少在大多数情况下，author 在实现过程中被迫经历了一遍系统：查代码、撞 constraint、理解 状态、debug、改 tests。这个过程很慢，却顺便把一些业务知识压进了人的脑子里。

AI 把中间最慢的一段压缩以后，链条变了：

```text
Ticket / prompt
→ Agent 生成 code + tests
→ 工程师选择 candidate
→ PR
→ Reviewer 面对一个完成度很高的 diff

```

现在，一个 PR 可以在 author 还没有形成完整 mental model 之前就出现。

Diff 看起来更像完成品，背后的理解却未必同比例增加。

如果 reviewer 仍然把任务定义成“把这几百行代码看一遍”，很容易发生两个极端：

- 因为不信任 AI，退回逐行 proofread，review time 暴涨；
- 因为 tests 都绿了，把 PR 当作已经完成，只检查明显问题。

一个看得太细，一个看得太浅。两边都可能漏掉两件件事：这个改动为什么应该存在；团队凭什么相信它。

## Review 的对象不是文本，是改动

我现在更愿意这样定义 code review：

> **Review 是团队决定是否愿意承担一个改动的过程。**

代码当然仍然是重要 evidence。很多时候，不读关键路径根本不可能判断风险。

但代码不是 review 的全部对象。真正需要判断的是五件事。

## 第一件：Intent Delta

先别急着打开 Files changed。

先问：

- 用户或系统行为到底改变什么？
- 原始问题、ticket 和 PR 描述是否一致？
- 这个实现回答的是不是原来的问题？

这一步听起来像 PM 的工作，其实不是。

PM 对问题和优先级负责，工程师对 change 如何进入系统负责。如果 PR author 不能用几句话解释 behavior delta，reviewer 大概率只能从代码反推 intent。

这相当于拿答案猜题目。偶尔能猜中，不适合当 operating model。

## 第二件：Invariants 和 Assumptions

AI 很擅长把缺口补成一个 plausible answer。

所以 reviewer 需要问：

- 哪些业务规则必须始终成立？
- 哪些 assumption 来自原始需求？
- 哪些是工程师的设计决定？
- 哪些可能只是 agent 为了完成实现而补出来的？
- 时间、权限、状态转换、并发和数据完整性有什么边界？

床位 bug 漏掉的不是一行语法，而是“系统按业务日判断占用”这个 invariant。

如果 invariant 没有进入 PR，逐行读得再认真，也只能检查代码是否忠实执行了一个不完整的问题。

## 第三件：System Fit

Agent 往往能快速完成局部任务，但它产生的局部答案必须放回整个系统里看。

Reviewer 需要判断：

- Repository 里是否已经有相同能力？
- 是否绕过现有 abstraction 或 contract？
- Change surface 实际有多大？
- 是否引入 migration、兼容性或长期 coupling？
- 这是一个合理增量，还是又在系统边上长了一块新代码？

AI 降低了新增代码的边际成本，没有同步降低未来理解代码的成本。

所以 review 不应该只问“这段能不能工作”，还要问“我们是否愿意以后继续拥有它”。

## 第四件：Verification Evidence

“Tests passing”经常是最让人安心的绿色。

问题是，code 和 tests 可能来自同一个 ticket、同一个 prompt，甚至同一个 agent。

它们可以完美一致，然后一起偏离业务 intent。

Reviewer 需要继续追问：

- Tests 验证的是业务行为，还是复述 implementation？
- 有没有 negative path 和 boundary case？
- 有没有来自历史 bug、production sample 或 domain expert 的 independent oracle？
- Generated tests 和 generated code 是否共享同一个 assumption？
- 如果判断错了，系统如何发现、隔离和恢复？

多个绿灯不一定是多份 evidence。有时候只是同一个 assumption 换了几个窗口显示。

## 第五件：Operability

一个 change 能通过 tests，不代表进入 production 后就可观察、可诊断、可恢复。

Reviewer 还需要检查：

- Logs、metrics、trace 是否足以定位问题？
- Dashboard 能否区分 rollout cohort 和 feature version？
- Feature flag 和 rollback 是否可用？
- Telemetry 的数据口径是否可信？
- PM / Ops 上线后能否判断功能真的在工作？

这里的责任边界很重要。

PM / Ops 负责 operational acceptance 和 outcome interpretation；Eng 负责 functional verification，以及让结果可验证的 evidence infrastructure。

Dashboard 不是工程师把责任交出去的仪式。如果埋点错了，PM 只会对一个错误数字进行更加专业的分析。

## Reviewer 不应该替 Author 第一次理解 Change

如果 author 提交的只有 diff，reviewer 就被迫做 context archaeology：翻 ticket、找 Slack、猜 prompt、读几百行代码，再问“所以我们为什么改这个？”

这正是 AI slop 对 attention 征税的一种方式。

Author 应该随 PR 一起提交一个最小 Evidence Package：

```text
Intent / Non-goals
Invariants
Assumptions
Change surface
Evidence produced
Evidence missing
Rollout / Rollback
Observability

```

它不需要是一份长文档。低风险 change 可能只需要 PR template 里的几段话。

重点是：author 是第一层 accountable aggregator。Reviewer 是独立判断，不是替 author 第一次建立 ownership。

## 先让机器处理机器擅长的部分

Human attention 不应该浪费在稳定可自动化的检查上。

进入 human review 前，可以先完成：

- Formatting、lint 和 types；
- Unit / integration tests；
- Dependency、secret 和基础 security scans；
- Failed gates 汇总；
- Duplicate-code 和 suspicious generated artifact 检查；
- PR size 和 change surface 摘要。

这些 gate 不能证明 change 正确。

它们的价值是减少低价值 attention demand，让 reviewer 把时间留给机器不擅长承担的判断。

## Review 不是只有 Approve 和 Request Changes

很多 review comment 都长得像 implementation patch：这里改名，那里抽函数，再补一个 null check。

新 Review Contract 需要允许 reviewer 更准确地说出问题在哪一层：

- Intent unclear；
- Invariant missing；
- Assumption unresolved；
- Evidence insufficient；
- System-fit concern；
- Operability gap；
- Safe to ship。

如果问题是 evidence 不足，就不要伪装成一条代码风格意见。

如果问题是 intent 不清楚，也不要让 author 再生成一版 diff 碰运气。

## 高风险代码还是得逐行看

对。

安全、账务、权限、数据迁移和关键状态机，很多时候就是需要逐行理解。AI 生成不构成少看代码的理由。

但这并没有推翻前面的论点。

> **逐行 review 可能是必要条件，但从来不是充分条件。**

你可以逐行确认每个时间比较都写对了，仍然漏掉“业务按天，不按秒”的问题。

所以问题不是“还要不要读代码”，而是先根据 risk 决定读到什么粒度，同时确保 intent、invariant、system fit、evidence 和 operability 没有被 diff 遮住。

按风险分配 attention 是第二章的问题。第五章只回答一件事：当 attention 已经投入 review，它应该判断什么。

## 下周可以做的一个实验

选一个正在进入 review 的 PR。

要求 author 先提交一页以内的 Evidence Package。Reviewer 暂时不要打开 diff，先写下：

1. 这个 change 的 intent 是什么；
2. 最大 assumption 或 risk 是什么；
3. 什么 evidence 足以接受；
4. 哪些代码路径需要重点阅读。

Review 结束后，把 comments 粗略分成：

- Implementation；
- Intent / invariant；
- System fit；
- Evidence；
- Operability。

如果绝大多数 comment 都是命名和局部写法，而 escaped defect 经常来自业务语义或系统边界，那不是 reviewer 不认真。

可能是 Review Contract 过时了。

Code review 没有因为 AI 失去价值。恰恰相反，当 authoring 变得廉价，团队更需要一个地方决定哪些 change 值得拥有。

只是这个决定不能只靠读完 diff。