第 4 章 · 贵族专制、民主政治和系统设计
题记借的是兰斯大教堂:它的风格"是一种风格上的极致",因为 Jean d’Orbais 构思的整体设计被后继建筑师遵守,“这就是这个宏伟建筑能够如此和谐统一的原因之一”。
这一章讲了什么
作者先用大教堂作对照。欧洲许多大教堂的不同部分风格迥异,因为后来的建筑师总想"提高",以反映自己的品味;而兰斯的和谐来自八代建筑师每个人的自我约束——他们各自牺牲了一点创意,换来纯粹的设计。
对照到软件上,他给出一个判断:计算机系统的概念差异通常不是因为跨越了几个时代,而是因为设计被切分成由若干人完成的若干任务。于是他提出本章的总纲——在系统设计中,概念完整性应该是最重要的考虑因素;宁可省略一些不规则的特性与改进,也不接受一个独立、无法整合的系统,“哪怕它们其实包含着许多很好的设计”。
接着他问四个问题:如何获得概念完整性?这是否意味着结构师贵族专制、压制实现人员的创造性?如何避免结构师写出无法实现或代价高昂的规格?如何与实现人员充分沟通细节?
“获得概念的完整性"一节的答案出人意料地落在易用性上。编程系统的目的是让计算机更容易使用,而代价是软件的外部说明规模达到计算机系统自身说明的 10–20 倍。只有当功能说明节省下来的时间超过学习、记忆和搜索手册的时间,易用性才真的提高。因此他的判断标准不是功能多少,也不是简洁本身,而是功能与概念复杂程度的比值。他举了两个反面参照:OS/360 以功能繁多被开发者推崇,PDP-10 分时系统以简洁精干被建造者称道——“一旦以易用性作为衡量标准,单独的功能和简洁都是不均衡的,都只达到了真正目标的一半”。简洁和直白最终来自一致性:语法上用相同的技巧,语义上有同样的相似性。
“贵族专制统治和民主政治"一节处理那个感情色彩浓厚的问题。前提是硬的:概念的完整性要求设计出自一个人、或者非常少数互有默契的人;而进度压力要求很多人参与开发。作者给出两条出路——仔细地把设计与实现分工,或者采用上一章的外科手术队伍。对非常大型的项目,把体系结构工作与具体实现分离是获得概念完整性的强有力方法:他在 IBM 的 Stretch 与 System/360 上见过它成功,也在 OS/360 上见过它因为没有被广泛采用而失败。
这里他把定义钉死了:体系结构是完整而详细的用户接口说明——对计算机是编程手册,对编译器是语言手册,对控制程序是语言与函数调用手册。体系结构陈述"发生了什么”,实现描述"如何实现”(Blaauw 用时钟举例:表盘、指针、旋钮是结构,里面的机构是实现)。而结构师的角色是用户的代言人:用专业技术知识支持用户的真正利益,而不是维护销售人员或制作者鼓吹的利益。
对民主的质疑,作者的回答分两层。好创意确实经常来自实现人员或用户,但不能与系统基本概念整合的好想法,最好放到一边;如果出现了多个互不兼容的重要构想,正确做法是抛弃原来的设计、合并基本概念、在新基础上重新开始。至于"贵族专制",他的回答是肯定的:必须有人控制这些概念,结构师的工作产物生命周期比实现人员更长,处在解决用户问题的核心地位——“这实际上是一种无需任何(强制的)贵族专制统治”。
“实现人员的创造性被压制"则被他直接归为误解:外部技术说明的编制并不比具体实现更有创造性,只是性质不同的创造工作;在给定体系结构下实现设计,同样需要新的思路与卓越才华,“产品的成本性能比在很大程度上依靠实现人员,就如同易用性在很大程度上依赖结构师”。他进一步反过来说,外部体系结构规定实际上增强了实现小组的创造性:毫无限制的实现小组会把精力耗在结构决策的争论上,对具体实现的关注反而更少。他引 Conway 的说法作证——PL/C 编译器"最终决定支持不经过改进和增强的语言,因为关于语言的争议已经耗费了我们所有的时间和精力”。
最后一节"在等待时,实现人员应该做什么"是全书最坦诚的一段自述。作者回忆 OS/360 外部技术说明的分工会议:体系结构经理有 10 人,需要 10 个月,比允许的进度多 3 个月;实现经理有 150 人,声称可以在体系结构队伍协助下按时交出高质量说明。他把工作分派给了实现队伍,结果两个结论都得到证实——推迟了 3 个月,质量更差,而概念完整性的缺失"至少增加了一年的调试时间"。他点明决定性因素:时间进度,以及让 150 名编程人员有事可做的愿望。
对有人的反对意见"体系结构队伍慢,实现人员只能干等",他的回答是时间顺序问题:在说明完成的时候才雇用实现人员,正如建造建筑的做法。但现实中总要压缩进度,于是他引用 Blaauw 的三阶段——体系结构、设计实现、物理实现——说明它们可以并行。在外部说明完成之前,实现人员有条件做很多事:设定明确的时空目标、弄清运行平台、设计模块边界、表结构、路径与阶段分解、算法与工具,并持续与结构师沟通;物理实现阶段也有库调整、系统管理、搜索排序算法等工作要做。所以,概念完整性"并不意味着该开发模式下的系统需要更长的时间来创建"。
我的判断
- 这一章是全书论证的枢纽:第 2 章证明了加人有害,第 3 章给出编队,本章回答"为什么必须由少数人决定概念"。三者拼起来才是完整的:人月神话不是关于人数,而是关于概念只能有一处源头。
- 我最认同的是把"易用性"当作最终标准,而不是把简洁或功能当成标准。这解释了一个常见困境:有的系统功能不多却难用(因为概念不统一),有的系统功能繁多却顺手(因为每条功能都服从同一套原理)。作者给的比值标准,比"少即是多"这种口号可操作得多。
- 但"不能整合的好想法就放一边"这条代价被低估了。作者假定系统的基本概念是正确且稳定的;如果基本概念本身选错了,这条规则会让整个项目沿着错误方向越走越整齐,而且因为一致性极好,反而更难被质疑。第 5 章讲第二系统效应时会从另一个角度回到这个问题。
- “外部规格实际上增强实现人员的创造性"这个论断,我认为是有条件的真理。条件写在后面那句里:规定必须"让人把注意力集中在没有人解决过的问题上”。如果规定把实现层面也管死了(细节到算法和数据结构),那就不是解放而是窒息。作者自己也承认第一个反对意见——规格说明里功能太多、成本考虑太少——是"危险的",并把讨论推到了下一章。
- 那场 OS/360 分工会的自我检讨值得反复看。他明明被说服了,明知结论会错,还是签了——原因不是判断力问题,而是"让 150 人有事可做"的压力。这类决策在项目里随处可见,也是这一章最有现实感的部分。
- 对"在说明完成时才雇用实现人员",我持保留态度:这在瀑布式的大型硬件项目里可行,但在人员与需求都变动的环境里几乎做不到,更现实的做法是让实现人员早期参与、但明确他们没有结构决策权。
和我手上的工作有什么关系
- 我自己的工作流里,“体系结构与实现分离"恰好是天然成立的:我先用文档和上下文确定目标与接口(体系结构),再让 Agent 去做实现。这一章给了我一条判据——如果我在结构还没定的时候就放手让它写代码,后面出现的分歧会以返工的形式收账,这一次的 9 倍是隐形的。
- 结构师是"用户的代言人"这句话,对个人项目也适用:没有人扮演用户时,我很容易替实现方便说话(“这样写更省事”),而不是替使用者说话(“这样用更顺手”)。这个小站从 OINK Starter 一路裁剪到现在,几乎每次返工都发生在后一种声音缺席的时候。
- “让 150 人有事可做"是我最容易重犯的错误,只是形态变了——我常常为了"让 Agent 别闲着"而并行开多个任务,结果在结构未定的时候产生互相冲突的产出。这一章的教训是:宁可让实现资源等结构,也不要让结构迁就实现资源的空闲。
一句话记住
概念完整性比任何单点功能的优劣都重要,而它只能来自少数人的一致决策;为此宁可让实现人员等结构,也不要为了让所有人都有事做而把设计切成碎片。