AI 代码审查之争:Uncle Bob「一行不读」vs Vibe Sled「审查滑坡」¶
AI 让代码生成速度指数级增长,但人类「认真审查的带宽」是有限且昂贵的资源。2026年7月,一场关于「读不读AI生成代码」的论战席卷整个开发者社区。核心不是读不读,而是审查带宽如何分配与定价。
目录¶
核心问题:审查瓶颈¶
人工审查的硬伤——2007 伯克利 Pvote 实验¶
Ka-Ping Yee 的博士论文《Building Reliable Voting Machine Software》中做了一个经典实验:
- 在一个 100 行的投票机程序(Pvote 的 Navigator.py)中故意植入 3 个 bug(easy / medium / hard)
- 邀请 4 位顶级安全专家(Mark S. Miller、Dan Sandler、Yoshi Kohno、Ian Goldberg)审查
- 告知审查者「这一区域有 bug」,但不告知数量
- 结果:花费约 20 个审查人时
- easy bug:70 分钟 ~ 2 小时内被 3 人发现
- medium bug:仅 1 人发现(Dan Sandler,约 70 分钟)
- hard bug:无人发现
「最令人震惊的是,一旦 bug 被指出,所有人都认为它们是'事后显而易见的',我们本应该能找到!」——Mark S. Miller(私下评论,未记录在论文中)
结论:即使把范围缩小到 100 行、告知有 bug、用顶级专家,人工审查依然无法保证发现刻意隐藏的缺陷。
审查带宽是稀缺资源¶
代码生成速度 审查带宽
┌──────────────────┐ ┌──────┐
AI → │██████████████████│ 指数增长 │████ │ 线性,几乎不增长
└──────────────────┘ └──────┘
↓ ↓
越来越多的代码 越来越不够用的审查能力
↓ ↓
└────────── 悖论 ────────────┘
逐行审查 → AI 速度优势作废
不审查 → 质量失控
AI 生成代码极快,但人类「认真阅读与理解的带宽」是有限且昂贵的资源。生成成本趋近于零,审查成本纹丝不动——这个剪刀差是整场争论的根源。
两阵营深度拆解¶
时间线¶
2026-07-03 2026-07-17 2026-07-23
│ │ │
Hashimoto 推文 Lemmer-Webber 博客 Uncle Bob 推文
"I read the code" "Faulty Towers, vibe "I read zero lines"
83万浏览 sickness & vibe bobsled" 480万浏览
← 收缩派的理论基础 → ← 收缩派的理论基础 → ← 改造派的核心立场 →
阵营 A(收缩派):Lemmer-Webber 与「Vibe Bobsled」¶
核心人物:Christine Lemmer-Webber,开源软件工程师,SproutCore/ActivityPub 贡献者。
博客原文:2026年7月17日发布《Faulty Towers, vibe sickness, and the vibe bobsled》——这是整个收缩派的理论基石。
Vibe Bobsled(雪橇效应)¶
Lemmer-Webber 用「雪橇」(bobsled)比喻 AI 编程的滑坡过程。雪橇运动的本质是:你坐在里面,沿冰道下滑,只有一个方向可去。
┌─ 阶段 1:「当自动补全用」
│ "我只是用 AI 做 fancy autocomplete"
│
├─ 阶段 2:「让 Agent 探索,我自己写」
│ "Agent 帮我试想法,代码还是我写"
│ ↓ 惯性加速
├─ 阶段 3:「Agent 生成,我会逐行审查」
│ "Agent 写代码没关系,我会 review 每一行"
│ ↓ 继续下滑
├─ 阶段 4:「不怎么看 review 了」
│ "Agent 可能比我写得还好,信它就行"
│ ↓
└─ 阶段 5:「不写 prompt 了」
"我连 prompt 都不想写了"
↓
最终:没人完整理解整个 codebase
「人们对自己在这段旅程中的掌控力,远不如他们自认为的那样强大。」——Lemmer-Webber
关键洞察:这个过程不是开发者主动选择的,而是被惯性推着走的。每一步看起来都合理,但回头看已经滑了很远。
Simon Willison 的诚实自述¶
连最严谨的 pro-genAI 作者之一 Simon Willison 也承认了这种滑坡。他最初定义「agentic engineering」时强调:
「我不会提交任何无法向别人解释清楚其工作原理的代码。」
但仅一年后,他写道:
「随着 coding agents 越来越可靠,我不再逐行审查它们写的代码了,即使是生产级别的。我知道让 Claude Code 写一个跑 SQL 查询的 JSON API,它就是能写对……但我没审查那些代码。我感到一种愧疚。」
两个声明之间只隔了一年。
审查成本悖论¶
「生成不是编程中最慢的环节。理论建构(Theory-building)和审查才是。但机器在生成上极快——如果你要审查它们的工作,你就没在利用它最强大的特性:速度。」
这就是矛盾所在:认真审查 → 浪费 AI 速度优势 → 审查第一个被牺牲。
Code Slop(代码垃圾)与 Vibe Sickness¶
开源社区正在被没人真正理解的 AI 垃圾代码(slop)淹没。维护者收到大量 AI 生成的 PR/Issue,无法判断提交者是否理解代码内容,也无法拒绝(否则显得无礼)。
「你想抗议 LLM,拒绝使用包含它们的软件——就像抗议汽油里加铅,方式是不呼吸,直到所有人都不往车里加铅。」——Glyph
你无法 opt out。这就是 vibe sickness(氛围病)。
Cindy Sridharan 的底线¶
分布式系统工程师 Cindy Sridharan(《分布式系统可观测性》作者)立场强硬:
「每当我听到有人说'代码全是 Claude 写的,我不知道它怎么工作的',我就认定这个人没有能力调试这些代码。你调试不了它,就没资格说自己拥有它、掌控它。」
能否调试,是掌控代码的明确界线。
收缩派核心主张¶
缩减 AI 使用范围,将有限的审查预算留给最致命的代码。
阵营 B(改造派/关卡派):Uncle Bob¶
核心人物:Robert C. Martin(Uncle Bob),《代码整洁之道(Clean Code)》作者,1960年代末开始编程,至今超过 60 年。
「我一行都不读」¶
2026年7月23日,Uncle Bob 回复 Ori Pomerantz 的推文(Pomerantz 说让 AI 直接编辑文件让他不舒服):
「我开始写代码的时间比你早得多,已经编程超过 60 年。但我现在的策略是——完全不去读 Agent 写出来的任何代码。」
这条推文获得 480 万次浏览(Hashimoto 那条 83 万)。
信任转移:从代码到验证体系¶
Uncle Bob 不是放弃质量控制,而是把信任从「代码本身」转移到「自动化验证体系」:
| 维度 | 传统做法 | Uncle Bob 做法 |
|---|---|---|
| 审查对象 | 逐行读 Agent 生成的代码 | 不读,审查验证体系 |
| 信任基础 | 人脑理解每一行 | 测试套件能否拦截错误 |
| 质量保证 | Code Review + 人工判断 | 单元测试 + 变异测试 + CI 卡口 |
| 角色转变 | 语法校对者 | 验证关卡的设计者 |
防御体系¶
Agent 生成的代码
│
▼
┌─────────────────────────────────────────────┐
│ 验证关卡 (Verification Gates) │
├─────────────────────────────────────────────┤
│ 1. 单元测试 (Unit Tests) │
│ 2. Gherkin 验收测试 (Acceptance Tests) │
│ 3. QA 流程 │
│ 4. 质量指标(圈复杂度、函数长度上限) │
│ 5. 测试覆盖率门槛 │
│ 6. 变异测试 (Mutation Testing) ★核心 │
└─────────────────────────────────────────────┘
│ 全部通过
▼
代码进入主干
变异测试(Mutation Testing)——防 AI 刷覆盖率¶
问题:AI 可能写「无效测试」——测试覆盖率 100%,但什么都没真正验证。
变异测试原理:故意在代码中注入微小错误(mutant),看测试套件能否抓到。
# 用 mutmut (Python) 或 Stryker (JS/TS) 做变异测试示例
pip install mutmut
# 对核心模块做变异测试
mutmut run --paths-to-mutate=src/payment/
# 查看结果
mutmut results
# 输出示例:
# 2._mutants_tested: 150
# 3.coverage: 87%
# 4.killed: 131 (87%)
# 5.survived: 19 ← 这 19 个 mutant 没被测试抓到,说明测试有盲区
| 指标 | 含义 | 健康值 |
|---|---|---|
| killed | 变异被测试抓到 | 越高越好 |
| survived | 变异没被抓到 | 越低越好 |
| mutation score | killed / total | 核心模块 ≥80% |
如果 AI 写的测试套件 mutation score 很低(大量 survived),说明它在「刷覆盖率」而非真正验证逻辑。
无限递归追问¶
Uncle Bob 的做法引来了层层追问,形成近乎「无限递归」的验证链:
Q1: 谁保证约束(测试)本身的可靠性?
A1: 让 Agent 写检查约束的工具(确定性、规模小)
│
Q2: 那你会审查这些检查工具的代码吗?
A2: 不会,同样走验证流程(工具也被测试包围)
│
Q3: 测试工具的测试谁来保证?
A3: 变异测试 + QA 流程 + Gherkin 验收
│
...Uncle Bob 认为关键是:
篡改一大批相互关联的测试来蒙混过关,难度远高于写一个能过的测试
Uncle Bob 对代码质量的立场¶
有人问:既然修改代码这么便宜,代码整洁还重要吗?
「代码质量依然重要,而且重要得多。混乱的代码不仅拖慢人,也会拖慢 Agent。我见过 Agent 被自己制造的混乱结构困住,来回折腾却解决不了,最后还需要我亲自理顺。」
→ 函数长度上限、圈复杂度限制、覆盖率门槛,这些约束从一开始就阻止 Agent 制造难以维护的结构。
两阵营对比总结¶
| 维度 | 收缩派(Lemmer-Webber) | 改造派(Uncle Bob) |
|---|---|---|
| 核心担忧 | 审查滑坡不可逆,最终没人理解系统 | 审查带宽浪费在语法层面 |
| 对 Agent 态度 | 信任会被惯性格外侵蚀 | 信任可以转移到验证体系 |
| 主张 | 缩减使用范围,守住审查 | 改造验证机制,人守关卡 |
| 代表做法 | 减少依赖,手动审查关键代码 | 变异测试 + CI 硬约束 |
| 共识区 | —— 两者都认为:人工逐行审查不可持续 —— |
Theo(t3.gg)的调和视角:
「对绝大多数工程师来说,目前阅读代码的比例太高了,但生成的代码还远远不够多。」
核心想法:用大量廉价代码(测试、变异、压力测试)去验证少量昂贵代码。
代码金字塔(Theo 的框架)
★ 核心代码(人工逐行审查)
/ \ ← 不能出错的部分
/ \ 手写 + 严格验证
/------\
/ \
/ 验证代码 \ ← AI 生成,成本低
/ (测试/变异) \ 保护核心
/________________\
/ \
/ 一次性脚本/实验 \ ← 看一眼都嫌多
/ (存在几小时就删除) \
/__________________________\
审查预算定价与三问决策树¶
影片的核心贡献:把「读不读」从二元对立变成资源分配问题。
三问决策树¶
[问题 1] 出错时,谁会第一个发现?
│
├── 测试自动报警 ──────────────────→ 风险较低
│
└── 用户投诉 / 生产事故 ──────────→ 风险极高
│
[问题 2] 从出错到被发现,隔多久?
│
├── 10 分钟内可定位 ──────────→ 风险较低
│
└── 几个月后才暴雷 ───────────→ 风险极高
│
[问题 3] 发现后,修复与损失代价多大?
│
├── 改一行代码即可 ──────→ 风险较低
│
└── 数据污染/资损/合规 ──→ 风险极高
按风险等级分配审查预算¶
| 风险等级 | 典型代码 | 出错信号 | 发现延迟 | 修复代价 | 审查策略 |
|---|---|---|---|---|---|
| 低 | 每周运行的临时报表脚本 | 运行报错 | 10分钟 | 改一行 | 交给测试体系,扫一眼都嫌多 |
| 中 | 内部工具、非核心功能 | 用户反馈 | 数天 | 数小时 | 抽查关键逻辑 |
| 高 | 支付回调验签逻辑 | 生产事故 | 数月 | 资损/合规 | 逐行人工审查 + 交叉审查 |
| 结构性 | 业务规则重复 4 次 | 测试通过但架构腐化 | — | 技术债 | 人工审查最该花钱的地方 |
结构性问题:测试能验证「当前行为正确」,但无法发现「架构冗余」。这恰好是人工审查最该投入的地方——AI 写出来的代码可能功能正确,但结构上重复、耦合、难维护。
判断矩阵¶
| 代码特征 | 推荐审查方式 |
|---|---|
| 有完善测试覆盖 + 低业务影响 | 自动化验证,人工抽查 |
| 无测试 + 高业务影响 | 逐行人工审查(优先补测试) |
| 有测试 + 高业务影响 | 人工审查结构 + 变异测试验证测试质量 |
| 纯基础设施(CI脚本/构建配置) | 轻量审查,关注可重复性 |
落地行动建议¶
四大行动¶
1. 模块盘点与定价¶
用「三问决策树」重新评估项目中每个模块,把精挑细选的人工审查时间花在发现慢、代价大的核心业务上。
你的项目模块清单
├── 支付回调验签 → 高风险(逐行审查)
├── 用户认证中间件 → 高风险(逐行审查 + 交叉)
├── 报表导出脚本 → 低风险(自动化即可)
├── 内部管理后台 → 中风险(抽查)
└── CI/CD 流水线配置 → 轻量审查
2. 导入变异测试(Mutation Testing)¶
挑选核心模块执行变异测试,检查现有测试套件是否真能捕捉代码异变。
# GitHub Actions 中集成变异测试示例 (Python / mutmut)
name: Mutation Tests
on:
pull_request:
paths:
- 'src/payment/**' # 仅对核心模块执行
jobs:
mutation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install mutmut pytest
- run: mutmut run --paths-to-mutate=src/payment/
- name: Check mutation score
run: |
SCORE=$(mutmut results --json | jq '.mutation_score')
echo "Mutation score: $SCORE"
# 核心模块要求 ≥80%
if (( $(echo "$SCORE < 80" | bc -l) )); then
echo "FAIL: mutation score below threshold"
exit 1
fi
主流变异测试工具:
| 语言 | 工具 | 特点 |
|---|---|---|
| Python | mutmut | 轻量,CLI 友好 |
| JavaScript/TypeScript | Stryker | 功能最全,支持多种框架 |
| Java | PIT (pitest) | 成熟,Maven/Gradle 集成 |
| Go | go-mutesting | 实验性 |
3. 硬性约束写入 CI(非 Prompt)¶
将圈复杂度、函数长度上限、覆盖率等指标做成 CI/CD 自动卡口——不合格直接阻断 Merge。
# .github/workflows/quality-gates.yml
name: Quality Gates
on: [pull_request]
jobs:
gates:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# 圈复杂度检查
- name: Cyclomatic Complexity
run: |
pip install radon
radon cc src/ -min C -nb -s --json > complexity.json
# 任何函数复杂度 > C 级别(>10)则失败
if [ -s complexity.json ]; then
echo "FAIL: functions with high complexity found"
cat complexity.json
exit 1
fi
# 函数长度上限
- name: Function Length
run: |
# 任何函数超过 50 行则失败
python3 scripts/check_function_length.py --max-lines 50 src/
# 覆盖率门槛
- name: Test Coverage
run: |
pytest --cov=src --cov-fail-under=85
| 指标 | 推荐阈值 | 工具 |
|---|---|---|
| 圈复杂度(Cyclomatic Complexity) | ≤ 10(C级别) | radon / complexity-report |
| 函数长度 | ≤ 50 行 | 自定义脚本 / eslint-plugin |
| 测试覆盖率 | ≥ 85%(核心模块 ≥95%) | pytest-cov / istanbul |
| 变异测试得分 | ≥ 80%(核心模块 ≥90%) | mutmut / Stryker |
4. 确立绿色通道规则¶
不读代码的权利需要逐类赢得。
绿色通道准入条件:
同一类型的变更必须连续出现 30 个干净无错的 PR
│
▼
逐步进入免逐行审查车道
│
▼
一旦出现 1 个事故 → 回退到逐行审查
│
▼
重新积累 30 个干净 PR
这避免了「一刀切免审」或「一刀切全审」两个极端。
最佳实践清单¶
代码审查预算分配 ✅/❌ 清单
✅ 核心业务逻辑:逐行人工审查 + 变异测试
✅ 支付/认证/合规:逐行审查 + 交叉审查 + 变异测试
✅ CI 质量门禁:圈复杂度 + 长度 + 覆盖率 全部自动化
✅ 绿色通道:30 个干净 PR 才准入
❌ 对所有代码一视同仁地逐行审查(浪费带宽)
❌ 对所有代码一视同仁地不审查(失控)
❌ 只看覆盖率不看测试质量(AI 刷覆盖率)
❌ 把质量约束写在 Prompt 里而非 CI 里(不可靠)
关键人物与原始来源¶
核心人物¶
| 人物 | 身份 | 立场 | 关键言论 |
|---|---|---|---|
| Mitchell Hashimoto | HashiCorp 联合创始人、Ghostty 作者 | 逐行阅读派 | "I read the code"(2026-07-03,83万浏览) |
| Christine Lemmer-Webber | 开源工程师,ActivityPub 贡献者 | 收缩派理论基础 | "vibe bobsled" 概念,审查滑坡不可逆 |
| Robert C. Martin (Uncle Bob) | 《Clean Code》作者,60年编程经验 | 改造派核心 | "I read zero lines"(2026-07-23,480万浏览) |
| Cindy Sridharan | 分布式系统工程师 | 调试底线派 | "调试不了 = 没资格说掌控" |
| Simon Willison | pro-genAI 代表作者 | 自我反思 | 从「必须审查」到「不再逐行审查」仅一年 |
| Theo (t3.gg) | 创业者/博主 | 调和派 | "用廉价代码验证昂贵代码" |
原始来源¶
- Uncle Bob 推文:https://x.com/unclebobmartin/status/2080257779395154409
- Lemmer-Webber 博客:https://dustycloud.org/blog/faulty-towers-vibe-sickness-and-the-vibe-bobsled/
- Hashimoto 推文:"I read the code"(2026-07-03)
- InfoQ 深度报道:https://www.infoq.cn/article/WbtENUlDowovNCHxECMf
- Pvote 论文:Ka-Ping Yee, Building Reliable Voting Machine Software (UC Berkeley, 2007)
- old-coder 开源 Skill(基于 Uncle Bob 理念):https://github.com/AmazingAng/old-coder
概念术语对照¶
| 影片用语 | 原始英文/准确说法 | 说明 |
|---|---|---|
| Vibe Sled / 雪橇效应 | vibe bobsled | Lemmer-Webber 原文用 bobsled(雪车),强调「只有一个方向」 |
| Vibe Sickness | vibe sickness | Glyph 首创,Lemmer-Webber 推广 |
| Code Slop | slop / code slop | AI 生成的似是而非的垃圾代码 |
| 变异测试 | Mutation Testing | 故意注入错误验证测试有效性 |
| 审查带宽 | review bandwidth | 人类认真理解代码的能力,有限且昂贵 |
参考资料¶
- InfoQ:编程界新分水岭——Uncle Bob 说「绝不读AI写的代码」,Hashimoto 却说他「逐行阅读」
- Lemmer-Webber:Faulty Towers, vibe sickness, and the vibe bobsled
- 腾讯新闻转载(同 InfoQ 原文)
- Uncle Bob 原始推文
- AmazingAng/old-coder(Uncle Bob 理念的开源 Skill)
- Ka-Ping Yee 博士论文:Building Reliable Voting Machine Software
相关笔记¶
- [[AI Agent 编程工作流]]
- [[变异测试 Mutation Testing 实践]]
- [[Clean Code 核心原则]]
文档生成时间:2026-08-06 基于 YouTube 视频 Pl9kjyRAwwQ(频道:为什么叫QQ)+ InfoQ/Lemmer-Webber 原始来源