跳转到内容

No Silver Bullet — 软件难度的二分手术刀

是什么

No Silver Bullet 是 Brooks 1986 提出的一把思维手术刀把软件难度切成两半——一半叫 essence(本质难度,长在问题里,砍不掉),一半叫 accident(偶然难度,是工具语言强加的,可以优化)。

日常类比:像盖房子。“房子要能住人、要承重、要防水”是 essence,换什么材料都得满足;“砌砖时手套破了 / 卷尺不够长”是 accident,工具更好就能省。

Brooks 的论断:未来 10 年(1986–1996)没有任何单一技术能本身带来 10x 的生产力提升。原因不是工具不好,而是 accident 那一半已经被高级语言、IDE 削得很薄,剩下的 essence 砍不动。所以”软件危机的银弹”——像狼人传说里那种一击致命的银子弹——不存在。

为什么重要

不理解这把手术刀,下面这些事都没法解释:

  • 为什么每隔几年就有人喊”X 是软件危机的银弹”,结果 10 年后回看都没兑现(4GL / OOP / AI 专家系统 / 自动化编程)
  • 为什么 Copilot / Cursor 是好工具但只给 1.5x,不是 10x
  • 为什么”加人到延期项目”不会更快(Brooks 定律是 essence 复杂度的直接推论)
  • 为什么”画个 UML 就让 PM 懂架构”是骗局(软件本质不可见)

核心要点

essence 不是一个抽象口号,Brooks 给了 4 个具体属性,每一个都解释为什么软件这么难:

  1. 复杂性(Complexity):软件里没有重复的原子组件。两段一样的代码会被你立刻抽成函数,所以”独特元素密度”极高。结果:bug 数 / 沟通成本 / 维护成本都随规模超线性增长。

  2. 一致性(Conformity):软件必须服从外部规则——银行 API 用 1980 年代格式、HTTP 大小写敏感、JSON 不许尾随逗号。这些没道理但你必须 conform,因为外面就这样。物理学家有”统一定律”可追求,软件工程师只有历史包袱。

  3. 可变性(Changeability):软件期望被改——这是它”软”的根源。建筑盖好不动,软件天天动。所以维护占总成本 60-90%,“完工”心态本身就是错觉。

  4. 不可见性(Invisibility):软件没有几何形状。建筑师有平面图 / 3D 模型一眼看出整体;软件至少 5 个正交维度(控制流 / 数据流 / 依赖 / 时序 / 命名空间),任何 2D 图都丢信息。

四个属性合起来撑死 essence。Brooks 说:accident 已经被压榨得不剩什么,单点突破上限就是 10x。

实践案例

案例 1:用三问拆穿”AI 编程银弹”

某新工具发布说”让开发提速 10 倍”。用 Brooks 三问:

问 1: 它减的是 essence 还是 accident?
→ 自动补全打字 = accident(表达层)
→ 不是 essence,所以天花板封死在 5-10x
问 2: 10 年单一技术 10x 能达成吗?
→ GitHub 2022 实验:+55%(约 1.55x)
→ 不是 10x,论断仍成立
问 3: 它的"essence-tackling"是真减还是降访问成本?
→ Cursor 的全仓库索引 ≠ 消除 invisibility
→ 是降低"看见软件形状"的认知成本,不是消除

结论:好工具,但别信 10x。

案例 2:重构遗留系统先分本质 vs 偶然

接手一个 5 年老系统,要重构。先列清单分类:

essence 类(数据模型耦合 / 业务规则散落 / 状态机不一致)
→ 啃硬骨头,需要业务理解,每条都要正面攻击
accident 类(编译慢 / 没 lint / 命名不一致 / 缺类型)
→ 工具能解,先做这些"快赢"

经验:先消 accident(1-2 周可见效果),再啃 essence(按月计划)。倒过来做会陷入”重构改不动 + 工具还烂”的双重泥潭。

案例 3:技术选型评审打分表

候选方案逐一对 4 属性打分:

def score_candidate(tech):
return {
"complexity": tech.reduces_unique_parts(), # 能减重复吗?
"conformity": tech.handles_external_specs(), # 帮你 conform 吗?
"changeability":tech.welcomes_change(), # 改起来痛吗?
"invisibility": tech.shows_system_shape(), # 让人看见全貌吗?
}

例:选”加 GraphQL”还是”REST + 文档”?GraphQL 在 conformity(schema 强约束)+ invisibility(schema 即文档)有加分,但在 complexity(解析器层)扣分。打完分再决定,别凭直觉拍板。

踩过的坑

  1. 把二分法当圣经而非框架 —— Brooks 的 essence/accident 边界本身在被 LLM 等工具重定义。机械套用会让你对真正的 paradigm shift 视而不见,看到任何新工具都本能贴 “accident 标签”。

  2. 误读”10x”的限定 —— Brooks 说的是”单一技术 / 10 年内 / 10x 单点提升”。生态累积 40 年(高级语言 + IDE + 包管理 + Stack Overflow + LLM)总收益远超 10x 但与他的论断不冲突。把 Brooks 当反 AI 工具的旗帜是误读。

  3. 把”银弹”当贬义攻击好工具 —— Brooks 没说工具无用,他说的是别承诺 10x。Copilot 给 1.5x、Cursor 给 1.5-2x 都是真好东西,只是不要被市场宣传带节奏。

  4. 忽略 4 属性的不对称性 —— complexity / changeability 几乎不可削弱(前者是规模本质,后者是软件定义);但 conformity / invisibility 可以靠”知识参数化”(LLM)和”仓库索引”(agentic IDE)部分降低访问成本。这是 Brooks 没预见到的 partial-essence-tackling。

适用 vs 不适用场景

适用

  • 评估市场上各种”X 是软件银弹”的过度宣传——三问拆穿
  • 重构 / 技术选型时区分”工具问题”和”问题本身的复杂度”
  • 给团队解释为什么”加人到延期项目”不会更快(Brooks 定律根源)
  • 帮新人理解软件维护成本为什么压不下去

不适用

  • 当成精确度量框架——essence/accident 的占比是渐近思想,不是可计算指标
  • 当反 AI 旗帜——Brooks 的论断与”AI 工具有用”完全相容,不要拉错战线
  • 解释组织 / 文化问题——Brooks 二分法没给”团队协作 / 远程 / 开源运动”留位置,那些是 Conway / Lehman 的领域
  • 评估单点新算法的理论收益——那是论文复杂度分析的活,不是这把刀

历史小故事(可跳过)

  • 1975 年:Brooks 写《人月神话》,复盘 IBM OS/360 项目(5000 人 / 10 年)。提出 Brooks 定律 / 第二系统效应 / 概念完整性。
  • 1980 年代初:他观察到一个怪圈——每过几年就有人喊”银弹”(结构化编程 → 4GL → OOP → AI 专家系统 → 自动化编程),每一波都说”这次不一样”。
  • 1986 年:Brooks 在 IFIP 大会做演讲 “No Silver Bullet”。副标题源自欧洲狼人传说——只有银子弹能杀狼人。
  • 1987 年:正式发表于 IEEE Computer Vol.20 No.4,约 9 页。
  • 1995 年:收入《人月神话》20 周年版第 16/17 章,加 ‘Refired’ 自审:预测准确,OOP / AI / 自动化都没兑现 10x,最大的”近银弹”是 buy-not-build 和快速原型。

学到什么

  1. 二分先于度量 —— 给一个混乱领域切一刀干净的分类(essence vs accident),比测量任何指标都更能让人想清楚问题
  2. 渐近论证比绝对论证更有力 —— Brooks 的”10x 上限”不是测出来的,是从”accident 已经被压薄”推出来的。简洁有力
  3. 承诺要节制 —— 真正经得起 30 年检验的论断都很谦虚(“没有任何单一技术…10x”),夸大的承诺都会被时间打脸
  4. 思维框架 ≠ 真理 —— Brooks 自己 1995 年就修正了部分论断(低估了组件市场和文化变革)。用框架但别迷信框架

延伸阅读

关联

  • beck-tdd —— 测试驱动是对 changeability essence 的工程化对策
  • hughes-fp-matters —— 函数式”模块化 = 高阶函数 + 惰性”是减 complexity 的另一刀
  • programmer-interruption —— invisibility 的微观证据:上下文一断就要 23 分钟才能找回
  • sillito-questions —— 程序员改代码时 44 类问题,每一类都是 invisibility 的具体表现
  • dijkstra-goto —— 结构化编程是 1968 的”银弹候选”,Brooks 1986 已把它归到 accident
  • hoare-logic —— program verification 是 Brooks 列的”局部 essence-tackling”候选

反向链接

  • beck-tdd —— Beck TDD — 用红绿重构循环让设计自己长出来
  • ci-effects —— CI Effects — 持续集成不是免费午餐,价值看实现细节
  • cognitive-load-theory —— Cognitive Load Theory — 学不会不是不努力,是工作记忆装不下
  • dijkstra-goto —— Dijkstra 1968 — Go To Statement Considered Harmful
  • fsrs-spaced-repetition —— FSRS — 让 Anki 知道每张卡什么时候快被你忘掉
  • hoare-logic —— Hoare Logic — 把”程序对不对”变成”数学证明对不对”
  • hughes-fp-matters —— Why FP Matters — 函数式真正赢在能拆能粘
  • programmer-interruption —— Programmer Interruption — IDE 数据告诉你被打断后多久才能继续敲代码
  • sillito-questions —— Sillito 44 问题 — 程序员改代码时到底在问什么