盘点一下:你的委派阶梯五级全亮了,KMP 重构 merge 了 4 万行 AI 改写的代码。现在问一个前七课都没问的问题:这 4 万行的复杂度,谁在守门?
第一课引过 Ousterhout 的战术/战略之分,这一课把他的整套复杂度框架精讲一遍,然后干一件所有前课铺垫好的事:把它装进你的 review 链——用第七课的 Review guidelines、第五课的独立 verifier、第六课的对抗验证,让"守复杂度的门"也成为可委派的流水线环节。
复杂度 = 让系统难以理解和修改的一切结构性因素。它只有两个来源,产生三种症状:
一个反直觉推论(原书原文):"有时多写几行代码的方案反而更简单,因为它降低了认知负担。" 行数不是复杂度的度量——读者需要知道多少才是。审 AI 代码时这条尤其重要:AI 爱交"看起来精巧"的短代码。
原书 §4.4 的原文公式(注意:流行说法"实现是收益"是二手转述,原文是功能):
信息隐藏:每个模块封装几项设计决策(知识),知识只体现在实现里、不出现在接口上。信息泄漏:同一项设计决策同时体现在多个模块——原书称其为"软件设计里最重要的 red flag 之一",且走"后门"的泄漏(不经接口、靠隐式约定)比接口泄漏更险恶,因为它不可见。典型病型:时序分解(temporal decomposition)——按执行顺序拆结构(read/modify/write 拆三个类,其中两个都得懂文件格式)。解法原则(原文):"按每个任务需要的知识组织结构,而不是按任务发生的顺序。"
这不是感觉,是测出来的。四组独立证据(注意 GitClear 是 review 工具厂商,数据有利益相关,但口径连续五年、样本 6.2 亿次变更):
| 证据源 | 关键数字 | 对应的 Ousterhout 病理 |
|---|---|---|
| GitClear 2025/2026 (1.5→6.2 亿行/变更) | 复制粘贴占比 9.4%→15.7%;重构性移动 21%→3.8%(粘贴:重构 ≈ 5:1);≥5 行重复块 +81%;跨文件函数调用(复用信号)-35%;错误掩蔽结构 +47% | Repetition(复制而非抽象)、信息泄漏(同一知识散落多处)、Nonobvious code |
| arXiv 2510.03029(2025) | LLM 代码 code smell 比人类基线高 63%;任务越复杂恶化越重 | 浅模块、命名类 red flags |
| arXiv 2605.02741(2026) | 模型越强、代码越臃肿越耦合(Volume-Quality 反比律);"详细 prompt 救不了架构退化"(原文:neither functional correctness nor detailed prompting mitigates this decay) | 换更强模型/写更细 prompt 都不是解药 → 只能靠设计边界 + review 门禁 |
| DORA 2024/2025 · SO 调查 2025 | AI 采用度每 +25%,交付稳定性 -7.2%(2025 仍负相关);开发者头号挫败感(66%):"almost right, but not quite" | 战术龙卷风的组织级代价 |
把三条线索拧成一句话:AI 的默认行为模式是复制代码块而非抽象共性、加参数/加分支而非重想接口、堆浅包装层而非挖深模块——而且模型更强、prompt 更细都不能自动治好它。解药只在你手里:预先给设计边界(第二、三课的 spec 与方案冻结),事后用 red flags 门禁(本课)。
原书书末的 red flags 全表——判据是原书原文的浓缩,第三列是它在 AI 生成代码里的高发形态(本课程综合实证整理)。这张表就是你 Review guidelines 的原材料:
| # | Red Flag | 一句话判据 | AI 代码典型表现 |
|---|---|---|---|
| 1 | 浅模块 Shallow Module | 接口相对功能过于复杂 | 一个 prompt 一层 wrapper:只转发调用的 service/util/helper 堆叠 |
| 2 | 信息泄漏 Information Leakage | 同一知识出现在多处 | 同一数据格式/协议的解析逻辑散落多个生成片段,各写各的 |
| 3 | 时序分解 Temporal Decomposition | 执行顺序反映在代码结构上 | 按 prompt 步骤直接拆 step1/step2/step3 函数,而非按知识边界 |
| 4 | 过度暴露 Overexposure | 常用功能的 API 逼用户了解罕用功能 | 内部选项全部提升为参数,调用方被迫理解不相关配置 |
| 5 | 传声筒方法 Pass-Through Method | 除了原样转发参数什么都不做 | 为"分层"而分层:controller→service→repository 同签名逐层转发 |
| 6 | 重复 Repetition | 同一段代码反复出现 | 最强实证:复制相邻代码块而非抽象共性(GitClear 5:1) |
| 7 | 通用特化混杂 Special-General Mixture | 通用机制里混入特定用例的代码 | 往通用函数里加 if 特判/新参数,而非重想接口 |
| 8 | 连体方法 Conjoined Methods | 不看另一个方法就无法理解这一个 | 多个生成函数共享隐式状态/约定,单看任何一个都不完整 |
| 9 | 注释复读代码 Comment Repeats Code | 注释信息从旁边代码一眼可得 | LLM 高发:// increment counter 式逐行复读 |
| 10 | 实现污染接口文档 | 接口文档描述使用时不需要的实现细节 | docstring 大段复述内部算法步骤而非使用契约 |
| 11 | 模糊命名 Vague Name | 名字宽到能指代很多东西 | data/result/process()/Manager 泛滥 |
| 12 | 起名困难 Hard to Pick Name | 找不到简单而形象的名字 | processDataAndValidateAndSave = 职责没切干净的信号 |
| 13 | 难以描述 Hard to Describe | 写不出简单而完整的注释 | 可反向工具化:让 AI 给自己的函数写一句话文档,写不清=设计问题探针 |
| 14 | 意图不明的代码 Nonobvious Code | 快速阅读无法理解含义和行为 | 能跑但意图不明;空 catch、宽泛 fallback 等错误掩蔽结构(+47%) |
第七课的伏笔现在收回。你的 review 链上有四个位置可以装这张表——而且调研确认:把 red flags 写成 Review guidelines / REVIEW.md 的公开现成例子还没有,你做完作业就是先行者:
@codex fix,发现→修复闭环。REVIEW.md 逐字注入每个 review agent 的 system prompt(最高优先级);本地 /code-review 的 effort 分级是 low→max(注意:ultra 不是 effort 级别,是云端多 agent 模式),低档少而准、高档广而可能含不确定项;--fix 直接把 findings 修进工作区。发版级用 /code-review ultra(每条发现独立验证)。## Review guidelines - 浅模块:新增的类/函数若只是转发调用、接口复杂度接近其功能价值,标记并建议内联或加深。 - 重复:发现 ≥5 行的相似代码块(哪怕不完全相同),标记并指出应抽象的共性; 禁止用"再复制一份"通过 review。 - 信息泄漏:同一数据格式/协议知识出现在两个以上文件时标记,指出应收敛到哪个模块。 (每条 = 判据 + 该怎么报告;只报影响正确性与可维护性的项,不报风格偏好)
## Review guidelines(Codex 侧)和 REVIEW.md(Claude 侧),然后对你 KMP 重构里已 merge 的一个单元跑 /code-review(记得换 fresh context 或换工具审,别让改代码的会话自审)。验收:至少产出 3 条带 red flag 归类的发现。把 ② 的发现清单和 ③ 的两个数字发我——它们决定你的 Review guidelines 第二版怎么改,也是第九课(常驻自治:让 Routine 每周自动跑这套审计)的输入。
1. 按原书原文,模块的收益和成本分别是什么?
2. 复杂度三症状里,Ousterhout 认为最糟的是哪个?为什么?
3. 2024-2026 实证里,AI 生成代码最强的一条病理证据是?
4. 为什么生成代码的模型不应该同时做它的 reviewer?
《A Philosophy of Software Design》第 2-5 章(约 50 页)——复杂度定义、战术/战略、深模块、信息隐藏的原始出处,AI 时代读比 2018 年更切身。时间紧就先读 Complexity Is the Ceiling(15 分钟)——它把整套框架直接接到了 LLM 行为上,"复杂度是你能委派给机器多少工作的天花板"。
点卡片翻面。记的是能用的判断核心,不是定义。
能讲清楚,才是真懂——比能回忆高一层。
讲不顺的地方就是还没真懂的地方 —— 发给我,我帮你补上。