第 2 章 · 人月神话
这一章的题记来自新奥尔良安托万餐厅的菜单:“美食的烹调需要时间;片刻等待,更多美味,更多享受。” 用菜来类比软件进度,是全文最狠的一处反讽:进度可以被顾客催,但菜不会因为被催就熟。
这一章讲了什么
作者开篇给出判断:在众多软件项目中,缺乏合理的进度安排是造成项目滞后的最主要原因,比其他所有因素加起来的影响还要大。然后列出五个成因:估算技术缺乏有效研究,隐含了"一切都将运作良好"的假设;估算技术隐含假设人和月可以互换,把进度和工作量混为一谈;经理对估算缺乏信心,没有耐心持续估算;缺少进度的跟踪与监督;以及一旦发现进度偏移,下意识的反应是增加人力——“这就像使用汽油灭火一样”。
接着他拆掉乐观主义。所有程序员都是乐观主义者,“这次它肯定会运行”,每一项任务都被假定只需花费它"应该"花费的时间。这里引用了 Dorothy Sayers《创造者的思想》里的三阶段:构思、实现、交流。只有进入实现,才会发现构思的不完整与不一致;而编程的介质又极其易于驾驭,于是我们期待实现过程不会遇到困难——乐观主义正是从这份"介质太顺手"里长出来的。
然后是书名所指的那件事。作者用四张图刻画人员与时间的关系:
| 任务形态 | 加人的结果 |
|---|---|
| 完全可以分解,彼此不需沟通 | 人月互换成立,加人真的能缩短时间 |
| 完全无法分解 | 加人对进度毫无帮助 |
| 可分解但子任务之间需要沟通 | 最好情况也比不分摊更差 |
| 关系错综复杂,需要多人协商 | 沟通开销彻底吞掉分解带来的收益 |
沟通成本由两部分组成:培训(技术、项目目标、总体策略、工作计划,这部分不可分解,随人数线性增长)和相互交流(若每个部分都要与其他部分单独协作,工作量按 n(n-1)/2 增长)。一对一交流时,3 个人的沟通量是 2 个人的 3 倍,4 个人是 2 个人的 6 倍。作者的结论是:软件开发本质上是系统工作,沟通很快会消耗掉任务分解节省下来的个人时间,添加人手实际上是延长而不是缩短进度。
后续三节处理具体环节。系统测试是进度安排中最不合理的部分,因为需要多少时间取决于缺陷的数量和缺陷难以捕捉的程度,而排期时的假设却是"理论上缺陷应该为零"。空泛的估算用煎蛋作比:顾客要求两分钟上菜,厨师只能把火开大,结果一面焦了另一面还是生的;出路只有两条——用数据(生产率图表、缺陷率图表、估算规则),或者经理挺直腰杆坚持自己的经验判断。最后是全章最著名的推演:
一个估计 12 人月、3 个人做 4 个月、设四个里程碑的任务,两个月后第一个里程碑没有达成。如果只是首段估算不当,剩余 9 人月要在 2 个月内完成,需要 4.5 个人,于是加 2 人;如果整体估算偏少,剩余 18 人月,需要 9 个人,于是加 6 人。作者随即算这笔账的代价:新人要占用一名有经验的老手培训一个月,等于额外投入 3 人月;原来的三部分工作要重新划分为五部分,某些已完成的工作必定丢失;系统测试必然被延长。结果是第 3 个月末还剩 7 个人月的工作,却只有 5 个有效人月——交付依旧延期,和没有加人一样,而团队规模已从 3 人变成 7 人以上,组织和任务划分都变了类型。所以他还给了另外两条出路:重新安排进度(引用硬件工程师 P. Fagg 的忠告"避免小的偏差"),或者削减任务。
我的判断
- 这条结论常被简化成"加人没用",但作者自己画了图 2-1 作为前提:任务能完全分解且无沟通需求时,人月互换是成立的。所以准确的表述是"当沟通成本超过分解收益时,加人才有害"。判断的边界在沟通结构,不在人数本身——这正是它今天仍然好用的原因。
- n(n-1)/2 这个模型很粗糙,它假设每一对成员都要单独交流且交流量相同。真实团队的沟通更像分层网络,规模大了会靠结构消解一部分成本。但它的方向是对的:沟通成本的增长快于人数的线性增长。今天的形式从"开会"变成了"同步消息、文档和上下文",曲线本身没变。
- 我对"持续估算"那条建议存疑。持续估算本身有成本,且需求变动越快估算的保质期越短。更可操作的做法也许是:不追求一次估准,而是让偏差尽早暴露——作者其实也承认进度监督属于另一篇论文。
- 空泛估算那一节表面在讲技术,实际点在组织:数据能否产生作用,取决于组织是否愿意接受数据带来的坏消息。如果图表只被用来追责,就没有人会认真提供数据。这一层他只用了一句话带过,但比图表本身更重要。
- 最值得学的是他的论证方式:不谈情怀,直接把 12 人月摊开,一步步算给你看。要让"加人"这个根深蒂固的直觉失效,只有这种算法比直觉更硬的方式才行。
和我手上的工作有什么关系
- 我现在的开发方式是单人加 Coding Agent 串行推进,天然绕开了沟通成本这一项——只有一个执行者时,n(n-1)/2 等于 0。这解释了为什么这套组合在小到中等规模的任务上效率极高;也标出了它的边界:一旦要靠多个 Agent 并行改同一块代码,沟通成本会以同样的曲线回来,只是形式变成了上下文同步与合并冲突。
- 系统测试那段对嵌入式项目格外刺耳。硬件相关的缺陷复现成本高、捕捉难度大,而排期时却按"缺陷为零"来算。可行的改法是按经验把测试时间显式写进计划,而不是等它超期后再解释。
- “避免小的偏差"是我这次读下来最想照做的一条。小延后最容易被默认吸收掉,一路累积到最后就变成无法解释的大延期。
- 煎蛋那个比喻值得单独记住:进度可以被要求,工作量不会因此改变。当我说"这个两分钟能做完”,需要自查是不是把顾客的期望当成了自己的估算。
一句话记住
人月不是可互换的量:任务一旦需要沟通,新增人力的沟通成本按 n(n-1)/2 增长,很快吃掉分解带来的收益——向进度落后的项目加人,等于用汽油灭火。