人月神话

人月神话

"success without applause, diligence without reward".

关于管理大型的计算机编程项目。本文仅仅用于记录,内容来源于《人月神话》,是清华大学出版的四十周年纪念版。

第一章 焦油坑 The Tar Pit

"A ship on the beach is a lighthouse to the sea."前车之覆,后车之鉴。

大型项目开发->焦油坑。

编程系统产品

程序、编程系统(接口、系统集成)、编程产品(通用化、测试、文档、维护)、编程系统产品(目标)

职业的乐趣

创建事物、开发有用的东西、组件组装、持续学习、神奇且灵活的创造

职业的苦恼

追求完美

设定的目标、供给资源、提供信息

依赖于他人(无可避免的,就像我讨厌让我写注释的,也讨厌别人不写注释的)

琐碎的bug、调试和查错

完成后陈旧过时...

第二章 人月神话 The Mythical Man Month

"Good cooking takes time. If you are made to wait, it is to serve you better, and to please you."

缺乏合理的进度安排 -> 项目滞后

乐观主义

年轻的程序员。一切都将运作良好,每一项任务仅花费它所”应该“花费的时间。

创造性活动有三个阶段:构思、实现、交流。而计算机编程基于十分容易掌握的介质,加重了乐观主义。构思总是有缺陷的,总会有各种各样的bug存在。

在单个任务中,”一切都将运作良好“是可能的,但当进行大型的编程工作时,任务数目多,且存在先后次序,导致一切正常的概率几近于零。

人月

错误的估计和进度安排中的工作量:人月。

对于成本,确实是可以以人月计,但进度并非如此。

用人月作为衡量一项项目的规模是一个危险和带有欺骗性的神话。

人数与时间仅仅在参与人员间不需要任何相互交流时可行。当任务由于次序限制无法分解时,添加人手不会对进度有帮助。

沟通增加的负担:培训和相互的交流。

月-人的关系图会呈v字形,也就是增加人数,耗时反而会增加。

系统测试

单元测试和系统测试受顺序限制最大。且时间难以估计。

时间占比 任务
1/3 计划
1/6 编码
1/4 构件测试和早期系统测试
1/4 所有构件已完成,系统测试

空泛的估算

为了满足客户需求,造成不合理的进度安排。

重复产生的进度灾难

当项目落后于进度时,增加人手、重新安排进度、削减任务都是可能的选择。

"Adding manpower to a late software project makes it later." --- Brooks法则,项目的时间依赖于顺序上的限制、人员的最大数量依赖于独立子任务的数量。

第三章 外科手术队伍

如何在有意义的进度安排内创建大型的系统?

问题

在优秀程序员和较差程序员之间存在生产率的差异。沟通增加的负担:培训和相互的交流以及更正沟通不当所引起的不良结果(系统调试)。

进退两难的境地:对于效率和概念的完整性来说,最好由少数干练的人员来设计和开发,而对于大型系统则需要大量人手,以使产品能在时间上满足要求。

Mills的建议

建议大型项目的每一个部分由一个团队解决,以类似外科手术队伍的方式组建,而非一拥而上。也就是说,同每个成员截取问题某个部分的做法相反,由一个人来完成问题的分解,其他人给予他所需要的支持以提高效率和生产力。

外科队伍 项目人员 职能
外科医生 首席程序员 定义功能和性能技术说明书,设计程序,编制源代码,测试,书写技术文档。
后备 副手 能完成任何一部分工作,但相对经验较少。主要作为设计的思考者、讨论者和评估人员。充当外科医生的保险机制。
老板 管理员 在人员、薪酬、办公室等方面具有决定权,但不能在这些方面浪费任何时间。需要有一个控制财务、人员、工作地点、办公设备的专业人员,充当与组织中其他管理机构的接口。可以服务两个团队。
编辑 考虑透明度,外科医生必须创建各种文档,编辑则根据草稿或口述进行重新分析和重新组织,提供各种参考信息和书目,对多个版本进行维护,并监督文档生成的机制。
文秘*2 管理员和编辑各一个。管理员的文秘负责非产品文件和项目协作一致。
程序职员 负责维护编程产品库中所有团队的技术记录。
工具维护人员 保证所有基本服务的可靠性,承担团队成员所需要的特殊工具(尤其是交互式计算机服务)的构建、维护和升级责任。
测试人员 设计测试用例、负责计划测试的步骤和为单元测试搭建测试平台。
语言专家 寻找一种简洁有效的使用语言的方法来解决复杂、晦涩、棘手的问题。

Mills概念的关键是“从个人艺术到公共实践”的编程观念转换。

如何运作

上述团队中7个专业人士在解决问题,而系统是一个人或两个人思考的产物,在客观上达到了概念的一致性。下图为10人程序开发队伍的沟通模式

团队的扩建

当面对大型任务时,该如何应用外科手术团队的概念呢?
关键在于提高每个部分的概念完整性。

第四章 贵族专制、民主政治和系统设计 Aristocracy、Democracy and System Design

概念的完整性

哥特式教堂上依附着诺曼底风格的十字架——上帝的荣耀、建筑师的骄傲

概念完整性在系统设计中是很重要的因素,为了反映一系列连贯的设计思路,宁可省略一些不规则的特性和改进,也不提倡独立和无法整合的系统。

获得概念的完整性

简洁和直白来自概念的完整性,每个部分必须反映相同的原理需求的一致平衡。在语法上,每个部分应使用相同的技巧;在语义上,应具有同样的相似性。因此,易用性需要设计的一致性和概念上的完整性。

贵族专制统治和民主政治

系统的体系结构是指完整和详细的用户接口说明。如Blaauw所说,体系结构陈述的是发生了什么,而实现描述的是如何实现。本书中的体系结构更偏向于现今的需求概念,而业界广泛认为的体系结构是系统的框架,属于设计层次。

结构师->贵族 是贵族专制统治,而非民主政治。

在等待时,实现人员应该做什么

整个创造性活动包括三个独立的阶段:体系结构(architecture)、设计实现(implementation)、物理实现(realization)。实际情况中,他们可以同时开始和并发地进行。

第五章 画蛇添足 The Second-System Effect

Adde parvum parvo magnus acervus erit.聚沙成塔,集腋成裘。

将制定功能规格说明的责任从开发快速、成本低廉的产品的责任中分离出来,有什么准则和机制来约束结构师的创造性热情呢?

结构师的交互准则和机制

  1. 牢记是开发人员承担创造性和发明性的实现责任,所以结构师只能建议而不能支配;
  2. 时刻准备着为所指定的说明建议一种实现的方法,同样准备接受其他任何能达到目标的方法;
  3. 对上述的建议保持低调和不公开;
  4. 准备放弃坚持所作的改进建议。

自律——开发第二个系统所带来的后果

结构师在开发第一个系统时更倾向于精炼和简洁。他知道自己对任务不够了解。

而设计第一个项目时,会有不断产生的装饰和润色功能。这些功能被暂时搁置,作为下一个项目的内容。当开发第二个系统时,信心满满。但是当着手第三个或者第四个系统时,先前的经验会相互验证,得到对此类系统通用特性的判断,而且系统之间的差异会帮助他识别出经验中不够通用的部分。一种普遍的倾向是过分地设计第二个系统。但添加的修饰功能和想法是一个“大馅饼”。

如何避免这种画蛇添足,这需要结构师有意识地关注这个系统的特殊危险,运用特别的自我约束准则,来避免那些功能上的过多修饰,根据系统基本理念及目的变更,舍弃一些功能。

第六章 贯彻执行 Passing the Word

He'll sit here and he'll say, "Do this! Do that!" And nothing will happen. ——Harry Truman, On Presidental Power.

他只是坐在那里,嘴里说:“做这个!做那个!”当然,什么都不会发生,光说不做是没有用的。

如果一个项目经理已经拥有行事规范、富有经验的结构师和许多编程实现人员,那么,他该如何确保每个人听到、理解并实现结构师的决策?如何保持系统概念上的完整性?

文档化的规格说明——手册

手册/书面规格说明:描述并规定了用户所见的每一个细节,是结构师主要的工作产物。手册不仅要描述包括所有界面在内的用户可见的一切,还要避免描述用户看不见的事物。后者是编程实现人员的工作范畴,而其设计和创造是不应该被限制的。体系结构设计人员必须为自己描述的任何特性准备一种实现方法,但是他不应该试图支配具体的实现过程。

规格说明的风格必须清晰、完整、准确。用户常常会提到某个定义,所以每条说明必须重复所有的基本要素,所有文字都要相互一致。尽管这使得手册枯燥无味,但精确远比生动更加重要。

规则说明会不断地被质疑、重复准备、修改。实现人员应该在进度表上有带日期的版本信息。

形式化定义

“不要携带两个时钟出海,带一个或三个。”该原则同样适用于形式化定义和记叙性定义。如果同时具有两种方式,则必须以其中一种作为作为标准,另一种作为辅助描述,并照此明确地进行划分。

直接整合

传播和推行定义:设计被传递参数或共享存储器的声明,并要求编程实现在编译时的一些操作来包含这些声明。

会议和大会

周例会:每周半天的会议,由所有的结构师、硬件和软件实现人员代表以及市场计划人员参与,由首席系统结构师主持。建议书在会议前书面分发。新问题讨论的重点是创新而不是结论。变更决策如果不能达成共识,则由首席结构师决定。

年度大会:为解决周例会未能解决的小要求、公开问题或者不愉快。一般持续两周。出席人员包括体系结构小组和编程人员、实现人员的结构代表,还包括编程经理、市场和实现人员,由项目经理主持。

多重实现

在大多数计算机项目中,机器和手册之间往往会在某一天出现不一致,人们通常会忽略手册。因为与机器相比手册更容易改动,并且成本更低。然而,当存在多重实现时,如实地遵从手册更新机器所造成的延迟和成本的消耗,比根据机器调整手册要低。

电话日志

对于结构理解和解释方面的问题,需要文字澄清和解释,但也有仅仅是理解不当的。所以鼓励打电话询问相应的结构师,而不是一边自行猜测一边工作。同时,上述问题的答案必须是可以告知每个人的权威性结论。

一种有用的机制是由结构师保存电话日志。日志中记录问题及答案,每周进行整合分发。

产品测试

独立的产品测试机构/小组:根据规格说明检查机器和程序,充当麻烦的代言人,查明每一个可能的缺陷和相互矛盾的地方。

第七章 为什么巴比伦塔会失败 Why Did the Tower of Babel Fail?

现在整个大地都采用一种语言,只包括为数不多的单词。在一次从东方往西方迁徙的过程中,人们发现了苏美尔地区的一处平原,并在那里定居下来。接着他们奔走相告说:“来,让我们制造砖块,并把它们烧好。”于是,他们用砖块代替石头,用沥青代替灰泥(建造房屋)。然后,他们说:“来,让我们建造一座带有高塔的城市,这个塔将高达云霄,也将让我们声名远扬;同时,有了这个城市,我们就可以聚居在这里,再也不会分散在广阔的大地上了。”于是上帝决定下来看看人们建造的城市和高塔。看了以后,他说:“他们只是一个种族,使用一种语言,如果他们一开始就能建造城市和高塔,那么以后就没有什么难得倒他们了。来,让我们下去,在他们的语言里制造一些混淆,让他们相互之间不能听懂。”这样,上帝把人们分散到世界各地,于是他们不得不停止建造那座城市。
——《创世纪》,11:1-8

巴比伦塔的管理教训

据《创世纪》记载,巴比伦塔是人类继诺亚方舟之后的第二大工程壮举,同时也是一个彻底失败的工程。单单从管理上看这个项目。

他们具有清晰的目标、充足的人力、丰富的材料、足够的时间、足够的技术。那为什么还会失败呢?

他们缺乏交流和交流的结果——组织。交流的缺乏导致了争辩、沮丧和群体猜忌。

大型编程项目中的交流

随着工作的进行,许多小组慢慢地修改自己程序的功能、规模和速度,他们明确或者隐含地更改了一些有效输入和输出结果用法上的约定。

团队如何进行交流沟通呢?

非正式途径。清晰定义小组内部的相互关系和充分利用电话,鼓励大量的电话沟通,从而达到对所书写文档的共同理解。

会议。常规项目会议上进行简要的技术陈述。

工作手册。项目的开始阶段。

项目工作手册

是什么?

对项目必须产出的一系列文档进行组织的一种结构。项目所有文档都应该是该结构的一部分。包括目的、外部规格说明、接口说明、技术标准、内部说明和管理备忘录。

为什么?

技术说明是必不可少的。

控制信息发布,确保信息能到达所有需要它的人手中。可以使用树状结构。

处理机制。

纸质版、微缩胶片、文档

大型编程项目的组织架构

如果项目有n个人,则有(n2n)/2(n^2-n)/2个相互交流的接口,有将近2n个必须合作的潜在团队。减少交流的方法是人力划分(division of labor)和限定职责范围(specialization of function)。

树状组织架构是作为权力和责任的结构而出现的。其基本角色——管理角色的非重复性——导致了管理结构是树状的。但交流结构是网状结构的。

对于树状编程队伍,每棵子树都应具备以下基本要素:

  1. 任务(a mission)
  2. 产品负责人(a producer):组建团队、划分工作、制定进度表。保证资源。与工作团队外部向上、水平地沟通。
  3. 技术主管或结构师(a technical director or architect):攻坚小组中的独行侠,勾画系统内部结构,提供设计的一致性和概念完整性,控制系统复杂度。遇到技术问题时,提供解决方案或按需调整系统设计。
  4. 进度(a schedule)
  5. 人力的划分(a division of labor)
  6. 各部分之间的接口定义(interface definitions among the parts)

对于产品负责人和技术主管,有三种可能的关系,在实践中得到了成功的应用。

  1. 产品负责人和技术主管是同一个人。通常是在很小型的队伍中。
  2. 产品负责人作为总指挥,技术主管充当左右手。存在困难,很难在技术主管不参与管理工作的同时,建立在技术决策上的权威。
  3. 技术主管作为总指挥,产品负责人充当左右手。

第八章 胸有成竹 Calling the Shot

Practice is the best of all instructors. 实践是最好的老师。

Experience is a dear teacher, but fools will learn at no other. 实践是最好的老师,但是,如果不能从中学习,再多的实践也没有用。

即使在不考虑相互交流沟通,开发人员仅仅回顾自己以前工作的情况下,工作量是规模的幂函数,该指数为1.5,即工作量=(常数)×(指令的数量)1.5工作量=(常数)\times (指令的数量)^{1.5}

Portman的数据

Aron的数据

Harr的数据

OS/360的数据

Corbato的数据

第九章 削足适履 The Pounds in a Five-Pound Sack

作为成本的程序空间

程序有多大?除了运行时间以外,它所占据的空间也是主要开销。同任何开销一样,规模本身不是坏事,但不必要的规模是不可取的。

规模控制

  1. 和制订驻留空间预算一样,应该制订总体规模的预算。和制订规模预算一样,应该制订后台存储访问的预算。
  2. 在指明模块有多大的同时,确切定义模块的功能。
  3. 为了满足目标,每个人都在局部优化自己的程序,很少会有人停下来考虑一下对客户的整体影响。培养开发人员从系统出发,面向用户的态度。

空间技能

数据的表现形式是编程的根本

第十章 提纲挈领

计算机产品的文档

大学科系的文档

软件项目的文档

为什么要有正式的文档

第十一章 未雨绸缪

试验性工厂和增大规模

唯一不变的就是变化本身

为变更设计系统

为变更计划组织架构

前进两步,后退一步

前进一步,后退一步

第十二章 干将莫邪

目标机器

辅助机器和数据服务

高级语言和交互式编程

第十三章 整体部分

提出bug的设计

构件单元测试

系统集成调试

第十四章 祸起萧墙

里程碑还是沉重的负担

“其他的部分反正会落后”

地毯的下面

第十五章 另外一面

需要什么样的文档

流程图

自文档化的程序

第十六章 没有银弹

摘要

介绍

根本困难

以往解决次要困难的一些突破

银弹的希望

针对概念上根本问题的颇具前途的方法

第十七章 再论“没有银弹”

人狼和其他恐怖传说

存在着银弹——就在这里

含糊的表达将会导致误解

Harel的分析

Jones的观点——质量带来生产率

那么,生产率的情形如何

面向对象编程——这颗铜质子弹可以吗

重用的情况怎样

学习大量的词汇——对软件重用的一个可预见但还没有被预言的问题

子弹的本质——形势没用发生改变

第十八章 《人月神话》的观点:是与非

第一章 焦油坑 The Tar Pit

第二章 人月神话 The Mythical Man Month

第三章 外科手术队伍

第四章 贵族专制、民主政治和系统设计

第五章 画蛇添足

第六章 贯彻执行

第七章 为什么巴比伦塔会失败

第八章 胸有成竹

第九章 削足适履

第十章 提纲挈领

第十一章 未雨绸缪!

第十二章 干将莫邪

第十三章 整体部分

第十四章 祸起萧墙

第十五章 另外一面

第一版结束语

第十九章 20年后的《人月神话》

为什么要出版20周年纪念版本

核心观点——概念完整性和结构师

开发第二个系统所引起的后果——盲目的功能和频率猜测

图形界面的成功

没有构建舍弃模型——瀑布模型是错误的

增量开发模型更佳——渐进地精化

作者

sonder

发布于

2025-01-21

更新于

2025-03-31

许可协议