题记与说明
- 精读日期:2026-11-06
- 条目前缀:
knowledge-bq_8bedt-2 - 研究类型:主题对照研究(跨三本经典 + 官方辩论 + 批评文献,共 9 个来源,7 个成功抓取精读)
- 一句话结论:三本书在"名字是意图的载体"上完全一致;在"函数该多小"上以 Ousterhout–Martin 官方书面辩论(2024–2025)告一段落——行数教条被双方共同放弃,意图/实现分离与深模块判据胜出,"隐藏副作用是谎言"成为全票通过的最不朽原则。
0. 阅读材料与检索路径
本次研究检索并精读了以下来源(按证据强度排序):
| # | 来源 | 类型 | 状态 |
|---|---|---|---|
| 1 | johnousterhout/aposd-vs-clean-code 官方书面辩论 README(Ousterhout vs. Robert Martin,2024-09 至 2025-02,114,599 字节原文) | 第一手(双方署名逐条对辩) | ✅ 已下载全文并逐行核对引语 |
| 2 | qntm: It's probably time to stop recommending Clean Code(2020-06-28) | 批评文献 | ✅ 已抓取 |
| 3 | Martin Fowler: FunctionLength (bliki)(2016-11-30) | 第一手(Fowler 本人) | ✅ 已抓取 |
| 4 | refactoring.com(《重构》第 2 版在线目录主页) | 第一手(Fowler 官方站点) | ✅ 已抓取 |
| 5 | Daniel Hofstetter: A Philosophy of Software Design 读书笔记(含章节级原文摘录) | 二手摘录 | ✅ 已抓取 |
| 6 | Henrik Warne: Book Review — A Philosophy of Software Design(2021-07-12) | 书评 | ✅ 已抓取 |
| 7 | bugzmanov: Clean Code Critical Analysis 第 2、3 章 | 逐章批评(含原文引用) | ✅ 已抓取两章 |
| 8 | ryanmcdermott/clean-code-javascript(via raw README 下载) | 社区现代适配 | ✅ 已下载 |
| 9 | Pearson 官方《Clean Code》样章 PDF | 原书样本 | ⚠️ 下载成功(1,167,426 字节)但 pdftotext 验证仅含前言,无第 2/3 章正文 |
检索失败的来源(如实记录):
- Goodreads《Clean Code》引语页:WebFetch 连接超时 + curl 抓取失败(无响应文件)。改用 WebSearch 摘要确认两条原文("FUNCTIONS SHOULD DO ONE THING…"、"Side effects are lies"),证据强度降一档。
- copyconstruct《Small Functions Considered Harmful》(Medium):连接超时,未能精读,其论点仅通过搜索结果摘要间接参考。
- WebFetch 不支持 application/pdf;改用
pdftotext(mingw64 版)本地抽取。
原书正文未直接持有,Clean Code / Refactoring / APOSD 的引语均通过上表来源转引,其中辩论 README 是三方引语(Ousterhout 引 Clean Code 原文并经 Martin 确认)交叉验证的最强来源。
1. 背景:三本书与一场官方辩论
- 《Clean Code》(Robert C. Martin, 2008):以"函数要小到 2–4 行""名字要自述"为代表的工匠式规范,是过去十几年代码评审清单的事实来源。马丁在辩论中透露其背景:"Back in 2008 my concern was breaking the habit of the very large functions that were common in those early days of the web."(debate.md:237)
- 《重构》(Martin Fowler;第 1 版 1999 用 Java,第 2 版 2018 用 JavaScript——refactoring.com 官方说明):不立规范,给"行为不变的受控变换目录":Extract Function、Rename Variable/Function……重构的定义:"a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior."(refactoring.com 首页)
- 《A Philosophy of Software Design》(John Ousterhout, 2018):以"复杂度 = 依赖 + 晦涩"为公理,提出深模块/浅模块框架:"The best modules are those that provide powerful functionality yet have simple interfaces."(Ch.4,经 Daniel Hofstetter 笔记转引)
- 冲突爆发点:qntm 2020 年批评文与 Ousterhout 2024–2025 年与马丁的官方书面辩论把"函数该多小"推到台前。辩论由四轮书面往返构成,主题依次为:方法长度、注释、PrimeGenerator 逐行重写、TDD。本文聚焦前三个主题中与命名/函数相关的部分。
2. 七维提取
2.1 核心问题
这份工作在解决什么问题:2008 年的《Clean Code》命名与函数规则,哪些在 2026 年、在《重构》的工程化框架和 APOSD 的复杂度理论映照下仍然成立?哪些已被作者本人或对手修订?——本质是给"代码风格遗产"做一次可证伪的筛选,而不是凭印象怀旧。
2.2 主要主张
- 命名层面三书全票共识:意图揭示命名(intention-revealing)、避免误导(disinformation)、名字是第一抽象工具,三者无分歧,连《Clean Code》最尖锐的批评者 qntm 也全盘认可这一半。
- 函数层面存在真实分歧,但已收敛:马丁("I'd rather err on the side of decomposition",debate.md:239)与 Ousterhout("teeny-tiny methods that suffer from both shallow interfaces and entanglement",debate.md:127–128)各自承认对方理论的一半,分歧收敛为权重之争——马丁总结:"We both value decomposition, and we both avoid entanglement; but we disagree on the relative weighting of those two values."(debate.md:645–646)
- Fowler 提供了独立于两派的第三判据:抽取函数的唯一可靠依据是"意图/实现分离 + 好名字",而非行数——这恰好是双方共识的可操作形式。
- 全票最不朽的一条:隐藏副作用(hidden side effects)是谎言——Clean Code 原则、qntm 批评、bugzmanov 逐章分析、辩论中 PrimeGenerator 案例四方独立指向同一点。
2.3 方法
技术路线:以"官方辩论原文(第一手)→ 三书各自的官方/准官方表述 → 批评者逐章核查 → 社区现代适配"四层证据链做三角验证:
- 用
curl下载辩论 README 全文(114,599 字节),用grep/sed按行号核对每条引语原文(debate.md:82–131, 237–240, 425, 645–646, 811–835); - WebFetch 抓取 Fowler 本人两处(FunctionLength bliki、refactoring.com)与 APOSD 两个笔记来源;
- 用批评来源(qntm、bugzmanov)做反向测试——能被批评者保留的原则才是真正幸存的原则;
- 用 clean-code-javascript(社区适配版)检验哪些规则在 2020s 的 JavaScript 语境下被保留/改造(如解构参数模拟具名参数)。
2.4 数据与证据
证据 A(辩论原文,逐行核对)——函数长度的直接交锋:
- Ousterhout 引 Clean Code p.34–35 原文并经马丁在场确认(debate.md:82–88):
"The first rule of functions is that they should be small. The second rule of functions is that *they should be smaller than that*." … "Functions should hardly ever be 20 lines long" … "just two, three, or four lines long" … "Blocks withinifstatements,elsestatements,whilestatements, and so on should be one line long."
- Ousterhout 的深模块判据(debate.md:96–99):
"The best methods are those that provide a lot of functionality but have a very simple interface: they replace a large cognitive load (reading the detailed implementation) with a much smaller cognitive load (learning the interface). I call these methods 'deep'."
- Ousterhout 的点名批评(debate.md:127–131):
"The advice in *Clean Code* on method length is so extreme that it encourages programmers to create teeny-tiny methods that suffer from both shallow interfaces and entanglement. Setting arbitrary numerical limits such as 2-4 lines in a method and a single line in the body of aniforwhilestatement exacerbates this problem."
- 马丁的两让步(debate.md:237, 239–240):
"Back in 2008 my concern was breaking the habit of the very large functions that were common in those early days of the web. I have been more balanced in the 2d ed."
"Still, if I must err, I'd rather err on the side of decomposition. There is value in considering, and visualizing decompositions. They can always be inlined if we judge them to have gone too far."
- 双方共同签署的分歧总结(debate.md:645–646):
"We both value decomposition, and we both avoid entanglement; but we disagree on the relative weighting of those two values."
证据 B(qntm 2020 批评,抓取确认):马丁自己对 2–4 行函数的论证是 "This is not an assertion that I can justify"(即无研究支撑);第 3 章示范代码 SetupTeardownIncluder 拆成 1 个私有构造器 + 15 个私有方法,多数 "do almost nothing and work exclusively through side effects"——示范代码违反了书中自己的副作用警告。qntm 总评:"a disarming combination of strong, timeless advice and advice which is highly questionable or dated."
证据 C(Fowler 的第三判据,bliki 原文):
"If you have to spend effort into looking at a fragment of code to figure out what it's doing, then you should extract it into a function and name the function after that 'what'."
Fowler 明确拒绝固定行数("No fixed rule"),自己的函数 "typically only a few lines long"、超过约六行 "starts to smell",并强调小函数只有在 "if the names are good" 时才成立。
证据 D(APOSD 命名与模块证据,经笔记转引):
- "The best modules are those that provide powerful functionality yet have simple interfaces."(Ch.4)
- "Pass-through methods are bad because they contribute no new functionality."(Ch.7)——直指为拆而拆的透传函数
- Ch.14 Choosing Names:"Good names are a form of documentation: they make code easier to understand.";"The most common problem with names is that they are too generic or vague.";以及关键的设计信号:
"If it's hard to find a simple name for a variable or method that creates a clear image of the underlying object, that's a hint that the underlying object may not have a clean design."
- Henrik Warne 书评确认对照关系:"It is interesting that this is the complete opposite of the advice in for example Clean Code."
证据 E(命名交锋,debate.md:811–835):Ousterhout 批评马丁的 "megasyllabic" 长名(如 isLeastRelevantMultipleOfLargerPrimeFactor):
"Developers effectively have to retype the documentation for a method every time they invoke it… The names are hard to parse and don't convey information as effectively as a comment… the traditional approach of using shorter names with descriptive comments is more convenient."
而马丁在辩论中给出的作用域规则反而与 APOSD 相容:"The larger the scope of a method, the shorter its name should be and vice versa."——双方在"别把文档塞进名字"上殊途同归。
证据 F(批评者反向测试):bugzmanov 逐章分析的结论——第 2 章 "Quite often the book declares a good rule but then shows horrible application",但保留清单里明确有:意图揭示命名的精神(getFlaggedCells 明显优于 getThem)、"avoid genuinely misleading names (real disinformation) is valid"、短而清晰优于长而啰嗦;第 3 章保留:"One Level of Abstraction per Function" 仍成立,Kent Beck 式 "Extract a helper" tidying 被认可,但 "extracting non-reusable methods doesn't actually reduce complexity or code size, at best it just improves navigation"。
证据 G(社区适配存活清单,clean-code-javascript raw README 实读):2020s 最流行的 Clean Code 适配版保留了:searchable names、函数参数 ≤2(改用解构模拟具名参数)、"Functions should do one thing"、拒绝 boolean 旗标参数、默认无副作用("Most things can be refactored to have no side effects!")——没有保留任何行数规则。
2.5 结论
仍成立(三书+批评者全票或近全票):
| # | 原则 | 依据 |
|---|---|---|
| 1 | 意图揭示命名:名字回答"为什么存在、做什么、怎么用" | Clean Code Ch.2(bugzmanov 转引原文);qntm 认可;APOSD "names as documentation";Fowler rename 系列重构 |
| 2 | 避免误导与含糊:disinformation / generic / vague 名字是负资产 | Clean Code Ch.2;APOSD Ch.14 "too generic or vague";qntm 认可 |
| 3 | 难命名 = 设计问题的信号:找不到简单的名字就去修结构 | APOSD Ch.14 显式表述;Clean Code "If a name requires a comment…" 同向;Fowler "抽取后命不了好名 = 不该抽" 同向 |
| 4 | 名字长度与作用域/生命周期匹配,反对 megasyllabic 长名 | 马丁辩论规则 + Ousterhout 长名批评 + Clean Code searchable-names 三方一致(这是辩论中少有的意外共识) |
| 5 | 隐藏副作用是谎言:函数改状态却看起来像查询,是一切追踪困难的根源 | Clean Code Ch.3 "Side effects are lies";qntm 与 bugzmanov 均认定这是全书最不朽部分;辩论 PrimeGenerator isNot… 隐式修改状态案例 |
| 6 | 单一抽象层级:函数体在同一个"意图层级"上叙述 | Clean Code "One Level of Abstraction per Function"(bugzmanov 认可仍成立);APOSD 深模块是同一思想的接口侧表述 |
| 7 | One Thing 保留为方向而非判据:函数应有一个可名状的意图,但判据换成"意图/实现分离 + 接口是否变浅" | 马丁 "One Thing" + 承认过度分解存在;Ousterhout 深模块;Fowler 意图/实现分离 |
| 8 | CQS(命令查询分离) | Clean Code Ch.3 "Functions should either do something or answer something, but not both."(源自 Bertrand Meyer;经检索确认原文) |
| 9 | Extract Function 本身:重构目录的第一操作,但触发条件是意图可命名,不是行数 | refactoring.com 目录 + FunctionLength bliki;Kent Beck tidying 认可(bugzmanov) |
应放弃或已被作者修订的:
- ❌ "函数 2–4 行 / if 块单行"作为普适规则——作者本人:"I have been more balanced in the 2d ed."(debate.md:237);qntm 指出其自认 "not an assertion that I can justify"。
- ❌ 分解越细越好——Ousterhout 的 shallow/entanglement 证据 + 马丁承认 over-decomposition(其极端例:
void doSomething() {doTheThing()})。 - ❌ 用超长自述名替代注释——Ousterhout "megasyllabic" 批评 + 马丁自己的作用域-长度规则;正确分工是名字承载意图、注释承载非显而易见的"为什么"。
- ⚠️ 参数个数的数字教条(零参最好)——方向正确(少参数=低耦合),但数字本身无证据;APOSD 的判据是接口整体复杂度而非个数;社区实践已改为"解构参数"等折中。
一句话提炼:三本书真正共同守护的是"代码按意图分层阅读"——名字是意图的索引(三人共识),函数是意图的容器(判据从"行数"修订为"意图/实现分离 + 接口深度"),副作用是意图的背叛者(全票)。
2.6 局限
作者承认的:
- 马丁在辩论中承认 2008 版对"如何判断拆分过度"着墨太少("I don't talk much, in the book, about how to make the judgement call",debate.md:237),且新版已更平衡;
- Ousterhout 在辩论中承认其对 TDD 的描述 "very short, dismissive, pejorative, and inaccurate" 并承诺修订(经仓库概览转述)——说明辩论双方都在修正。
我判断的:
- 原书正文未直接持有:Clean Code Ch.2/3 的引语全部经二手转引(bugzmanov/qntm/WebSearch 摘要),Pearson 官方样章 PDF 实测只有前言(
pdftotext验证 2,630 行无第 2/3 章内容),Goodreads 直抓失败。"FUNCTIONS SHOULD DO ONE THING…" 与 "Side effects are lies" 两条的原文精确度依赖搜索摘要确认,证据强度比辩论原文低一档。 - APOSD 引语同样转引:Daniel Hofstetter 笔记未直接收录 Ousterhout 批评小函数的原句,"浅方法"批评主要来自辩论原文与 Ch.7 透传方法段。
- 样本偏差:qntm/bugzmanov 都是有立场的批评者,其"保留清单"可能偏向结构主义视角;copyconstruct 名文(Small Functions Considered Harmful)因 Medium 超时未能精读,缺一个重要中间派声音。
- 无实证数据:三方论战至今以"名家长文对轰"而非受控实验方式推进——"2–4 行是否真的更差"没有 RCT 级证据,本笔记的裁决本质是权威与逻辑收敛,不是实证结论。
- Clean Code 2nd ed. 细节未知:马丁多次提及(debate.md:1853 "This is the term I use in *Clean Code 2d ed.*"),但本次未核实新版具体改了哪些规则。
2.7 对我的启发
- 给 AI 生成代码的评审清单:LLM 写代码恰好会犯两种极端——超长函数(bottom-up 补丁式生成)或机械拆分(被 Clean Code 语料过拟合后的 teeny-tiny 函数)。这份"仍成立清单"可直接作为 prompt/review 规则:判意图可命名、查隐藏副作用、查误导名,不查行数。
- 命名困难是最便宜的静态分析:让 AI(或自己)为一个函数起名,起不出来 = 结构有问题。APOSD 把它形式化为设计信号,这在自动化工作流里可以作为零成本的"设计坏味道探测"。
- 深模块思想迁移到工作流设计:我自己的自动化脚本/子代理封装也适用"简单接口 + 丰富实现"——
submit_result、一次精读任务输入输出就是深模块的实例;反例是被迫透传十个字段的浅接口。 - 阅读经典的方法论:面对"过时了吗"这类问题,最优路径不是找新的二手批评,而是找当事人正面交锋的原文(这场辩论就是)——比任何书评的信号密度高一个量级。
3. 三书对照表:命名
| 维度 | Clean Code (2008) | Refactoring (1999/2018) | APOSD (2018) | 裁决 |
|---|---|---|---|---|
| 名字的本质 | 意图的自述("If a name requires a comment…") | 重构的基本操作(Rename 系列是最低成本最高频) | 抽象与文档("Good names are a form of documentation") | ✅ 一致 |
| 误导名 | Avoid Disinformation(accountList 例子) | Rename 的动机条款 | "too generic or vague" 是最常见问题 | ✅ 一致 |
| 长名 vs 注释 | 倾向超长自述名 | 中性(名字+注释并用) | 明确反对 megasyllabic,主张短名+好注释 | ⚠️ 真实分歧,APOSD 侧得到批评者与辩论支持 |
| 起名困难 | 隐含信号(名不如注 = 名不达意) | 抽取后命不了好名 → 分解不当 | 显式公式:难命名 = 底层对象设计不干净 | ✅ 方向一致,APOSD 最强 |
| 搜索性/一致性 | searchable names、一词一义 | 目录内命名严格统一 | 一致性是名字的核心要求之一 | ✅ 一致 |
4. 三书对照表:函数
| 维度 | Clean Code (2008) | Refactoring | APOSD | 裁决 |
|---|---|---|---|---|
| 长度 | 2–4 行,if 块单行 | 无固定规则;超六行 "smells"(个人经验) | 深度 > 长度;反对数字限制 | ❌ 行数教条废弃,✅ "小"保留为启发 |
| 拆分依据 | One Thing + 单一抽象层级 | 意图/实现分离 + 好名字 | 接口是否变深(认知负担下降) | ✅ 三个判据可统一为"意图分层" |
| 过度拆分 | 未讨论(作者承认) | 隐含(Inline Function 是逆操作) | shallow + entangled 两个病名 | ✅ APOSD 提供诊断学 |
| 参数 | 零参最好,三参避免 | Replace Parameter with Query 等目录 | 接口复杂度整体评估,无数字教条 | ⚠️ 方向对,数字废弃 |
| 副作用 | "Side effects are lies" | 行为保持是重构的定义 | 深模块正是"封装副作用"的手段 | ✅ 全票,最不朽 |
| CQS | 明确条款 | 隐含在目录中 | 未强调但相容 | ✅ 大体成立 |
5. 重要原文引述汇编(按来源)
- Clean Code p.34–35(经 Ousterhout 引用、马丁确认,debate.md:82–88):"The first rule of functions is that they should be small. The second rule of functions is that *they should be smaller than that*."
- Clean Code Ch.3(WebSearch 确认原文):"FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. THEY SHOULD DO IT ONLY." / "Side effects are lies." / "Functions should either do something or answer something, but not both."(CQS,承 Bertrand Meyer)
- Clean Code Ch.2(bugzmanov 转引):"If a name requires a comment, then the name does not reveal its intent." / "Methods should have verb or verb phrase names" / "Shorter names are generally better than longer ones, so long as they are clear."
- Fowler, FunctionLength (2016):"If you have to spend effort into looking at a fragment of code to figure out what it's doing, then you should extract it into a function and name the function after that 'what'."
- refactoring.com(第 2 版定义):"a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior."
- APOSD(Daniel Hofstetter 笔记转引):"The best modules are those that provide powerful functionality yet have simple interfaces." / "Pass-through methods are bad because they contribute no new functionality." / "If it's hard to find a simple name for a variable or method that creates a clear image of the underlying object, that's a hint that the underlying object may not have a clean design."
- qntm (2020):马丁自认 "This is not an assertion that I can justify";总评 "a disarming combination of strong, timeless advice and advice which is highly questionable or dated"。
- 辩论收官(debate.md:645–646,马丁):"We both value decomposition, and we both avoid entanglement; but we disagree on the relative weighting of those two values."
6. 来源链接
- Ousterhout vs. Martin 官方辩论全文:https://github.com/johnousterhout/aposd-vs-clean-code (原文 raw:https://raw.githubusercontent.com/johnousterhout/aposd-vs-clean-code/main/README.md)
- qntm, *It's probably time to stop recommending Clean Code*: https://qntm.org/clean
- Martin Fowler, *FunctionLength*: https://martinfowler.com/bliki/FunctionLength.html
- Refactoring 第 2 版在线目录: https://refactoring.com/
- Daniel Hofstetter, APOSD 章节笔记: https://books.danielhofstetter.com/a-philosophy-of-software-design/
- Henrik Warne, APOSD 书评: https://henrikwarne.com/2021/07/12/book-review-a-philosophy-of-software-design/
- bugzmanov, Clean Code Critical Analysis(第 2/3 章): https://bugzmanov.github.io/cleancode-critique/chapter_2.html / https://bugzmanov.github.io/cleancode-critique/chapter_3.html
- ryanmcdermott/clean-code-javascript: https://github.com/ryanmcdermott/clean-code-javascript
- Pearson 官方样章 PDF(仅前言): https://ptgmedia.pearsoncmg.com/images/9780132350884/samplepages/9780132350884.pdf
*本笔记为独立精读条目(前缀 knowledge-bq_8bedt-2),未改动其他条目笔记、matrix.csv、backlog 或 nightly-log.md。所有引语均可通过上列链接复核;转引与直引的区分已在正文标注。*