读书笔记:人月神话

大学的时候上软件工程课程的时候记得当时老师对《人月神话》这本书很推崇,也不是很理解简单的软件编程和软件工程之间其实有很大的区别,工作之后从“一个人的工作”边成“多人协作”的过程,开始有一些新的感悟,打算读一读《人月神话》,深刻理解一下什么叫“没有银弹”,理解软件工程的边界在哪里。


第一章 焦油坑

编程系统产品演进

第一章上来就给出了一张图说明编程系统产品和纯粹的编程之间的区别,将程序转化为产品需要测试和文档,花费将是纯粹编程的三倍,而作为系统需要详尽测试接口,花费又将是原来三倍,因此一个成熟的编程系统产品花费将是原来的九倍之多。


第二章 人月神话

第二章上来就点明项目滞后的最主要原因是进度安排不合理,在项目中通常很难估算工期,然后即将延误时候又错误认为增加人手可以解决眼前的问题。

人数增加使得工时减少这一特性有一个前提条件,是任务必须能拆分给多个人完成。当完成任务的人之间需要交流才能完成任务时,沟通的成本也要被计算在时间成本之内。

需要沟通任务人员时间关系

更糟糕的是,随着人数的增加,沟通的成本也在不断的增加,这个增加的成本应该是人数 n 的平方量级的。

对于时间的安排,软件测试的时间往往是最容易被忽视但是最容易出问题的。多数大型系统项目的测试时间花费了近一半的时间,比预估的情况多很多。

总而言之,向进度落后的项目增加人手,需要考虑人员培训、重新分配、沟通等成本,效果往往不尽如人意。


第三章 外科手术队伍

第三章提出在软件开发过程中,成本的主要构成部分是人员的沟通成本,因此应该尽可能精简开发人员的数量。

这一章节提出一种很有创造性的概念,就是采用外科手术的方式安排相对应的工作,每个团队拥有少量的“外科主刀医生”以及一系列分工明确的技术支持人员。


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

第四章提出在软件开发过程中,应该由一小撮经验丰富的工程师来决定整体的架构,制定设计统一的规范,然后再由广大的开发人员在规范的约束下完成工作。

设计和实施的阶段应该分离开来,一个好的设计不能是“民主投票”产生的结果,需要注意的是,在规范下高效的完成对应的工作同样是一种创造性很强的工作。


第五章 画蛇添足

第五章讲述了架构师工作上需要注意的两个点:

  1. 在设计过程中与代码的开发人员充分的交流
  2. 谨防“第二次开发”的陷阱,具体就是指在设计过程中考虑了太多不必要的功能,第一次开发一般而言都比较谨慎,设计的都是仅仅能满足需求的最小功能集,第二次则会添加过多不必要的功能,再往后就能从多次经验中抽取出一个系统必要的功能集合了。

第六章 贯彻执行

第六章讲述架构师工作的具体流程,如何定义一份规范的用户手册。


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

第七章讲述了沟通和组织的相关问题,沟通需要采用文档确定团队人员上下一致,组织的部分很有意思,和之前知道的项目管理的部分连上了,技术主管带队攻坚项目,项目经理负责处理其他的琐碎事务。


第八章 胸有成竹

第八章主要讲述代码量和工作时间的相关关系,本章节给出了一个经验公式:

\[工作量 = 常数 \times 指令的数量^{1.5}\]

同时提出在协作人数增加的条件下,工作的效率将会下降,原因是沟通的成本在不断的增加。

同时不同工作由于难度的不同,一定代码量所需要的工时也有所区别,难度更高的工作通常需要更多的工作时间。


第九章 削足适履

第九章的内容现在看起来稍微有一点过时,它说的是在存储空间不足的情况下开发系统需要做出取舍和优化,有几个方案可以选择:

  1. 限制软件的规模,以达到空间上的效益最优化。(ps. 一些手机软件应该进来挨打,用起来肉眼可见的卡顿,恨不得什么都加载到内存里)
  2. 时间和空间上的平衡,使用时间复杂度稍高的代价换取较低的空间复杂度,或者反过来。

第十章 提纲挈领

第十章讲述了软件开发过程中的一些正式文档,以及讨论了为什么需要这些文档:

  1. 文档可以帮助人们厘清矛盾,确定策略。
  2. 文档可以起到团队成员沟通的作用,确保大家朝着共同的目标努力。
  3. 文档可以作为数据基础和进度检查的基础。

第十一章 未雨绸缪

这一章节讲述在开发的早期,需要准备一个抛弃的“原型”作为试验品,理由是当一个想法第一次实现时,往往存在过多的问题而无法进行修复,这样的东西也难以使用,因此不应该交付给用户。

只有先做出一个“原型”来发现主要的问题,之后从头再开始设计才会有比较好的效果。

之后提出了一个很有趣的问题,就是说当项目发生变更之后,之前的团队也要发生相对应的变更,这一点往往是很困难的,有时团队需要更多的高级项目经理来设计方案、处理琐事;有时又需要更多的高级程序员来赶进度。最优的方案就是这两者的角色可以适时的转换,这要保证高级项目经理的“权力”和高级技术专家是相当的,但是这一点往往很难做到。

本章节还讨论到程序开发的过程中,修复原有 bug 往往会引入新的问题,这使得测试的成本在后期很高,因为一个小小的修改需要运行所有的测试用例以保证没有对其他模块产生影响,应该尽可能指明模块的副作用或者书写没有副作用的模块。


第十二章 干将莫邪

第十二章的内容也稍显过时,讲述的是整个过程中通用工具的重要性,目前而言,无论是编程所用的工具,或是文档管理工具、亦或是进度管理工具,各个小组或者公司一般都有统一的规范,也有开发专业工具和通用工具的小组。


第十三章 整体部分

第十三章再次讨论如何减少一个系统中的 bug 数量,首先就是设计文档应该尽可能的详细,其次整体上应该有一个好的设计,还讨论了流程控制结构中 goto 的弊端,作者提出不仅仅要考虑代码层面的流程控制,更重要的是整体结构上的流程控制。

本章节还提出了一些关于系统测试的思路,大致就是需要对每个模块进行详尽的测试,确保没有问题之后结合到原有的系统中,同时整个系统进行回归测试。


第十四章 祸起萧墙

第十四章对于里程碑做了非常详细的定义,它要求被定义的非常明确,有确定的、可度量的事件。当里程碑是一个模糊不清的度量的时候,小组成员倾向于多上报自己的进度。

当项目的进度已经出现拖延时,项目经理为了防止老板干扰自己的工作,倾向于对拖延的进度隐瞒不报,解决这个问题的方法是一方面项目经理应该详细的上报进度让老板安心,另一方面老板也应该尽可能的不要越俎代庖,插手项目经理的工作。


第十五章 另外一面

第十五章再次声明文档的重要性,并且手把手说明一个程序文档中应该包含哪些内容。


第十六章 没有银弹

在未来的十年内,无论是在技术还是管理方法上,都看不出有任何突破性的进步,能够保证在十年内大幅度的提高软件的生产率、可靠性和简洁性。

第十六章首先将软件活动拆分为主要活动和次要活动,主要活动是设计一种复杂的“概念系统”的活动,而次要活动是将概念通过编程在计算机上模拟出来,由于主要活动的时间很难压缩,因此软件生产率将会受到很大的瓶颈。

在设计的活动上,需要详细的考察市场的空缺,并且通过迭代逐步地进行开发。

软件主要活动本身具有很糟糕的特性,即使次要活动的种种瓶颈得以解决,总体的生产率也无法获得突破。

我认为软件开发中困难的部分是规格说明、设计和测试这些概念上的结构,而不是对概念进行表达和对实现逼真程度进行验证。

软件具有在以下几个方面存在挑战:

  1. 复杂性:计算机状态复杂性、模块不相同、元素以非线形方式交互……
  2. 一致性:各种接口和系统没有统一的定义和接口。
  3. 可变性:很多工程例如建筑的修改成本很高,而软件的修改成本很低,同时软件依赖的环境不断发生变化迫使软件发生变化。
  4. 不可见性:软件模块之间的关联关系相当复杂,不是较少层次的扁平结构。

软件在次要活动上取得了一些突破,包括:

  1. 高级编程语言
  2. 分时
  3. 统一编程环境

后面说了一些次要活动的进步和可能的进步,得出结论就是关键问题无解,稍好一点开发软件的方式就是“增量式开发”


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

第十七章基本就是又写了一遍十六章内容,然后引用了一些当时批驳他的论文逐一驳斥,主要还是说明次要活动可以被各种抽象、各种简化,但是主要活动的几个糟糕的特性无法解决,作者悲观地看不见工具。


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

这一章节是作者在多年之后逐个回顾 1975 年版《人月神话》每一章节的内容并加以评述。

在第七章中作者修改了自己的观点,之前他认为每个团队成员应该了解所有的工作手册内容来减少沟通成本,但是 Parnas 说服他每个人工作的部分应该被封装,其他人都不应该了解别人部分的内部结构和实现,只应该了解对应的接口。


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

软件项目管理并不像大多数程序员起初认为的那样,而是更加类似于其他类型的管理……《人月神话》是关于人与团队的书,所以它的淘汰过程会是缓慢的。

作者在本章再次回顾之前的内容,并且对部分内容进行进一步阐述和修正。

首先是第十一章的内容,作者之前认为应该开发用于“舍弃”的版本,但是在这里作者阐述这是受到“瀑布模型”的误导,瀑布模型存在两个严重的问题:

  1. 将测试放到全部编码完成之后,使得错误不能在早期被发现
  2. 假设项目开发只经历一次过程

最后详细介绍了一下增量开发模型。


读后感

当人们习惯了呼吸的时候,就忘记了空气的存在。

粗略的看完这本书,发现软件工程课程上面很多东西都是有迹可循的,而作者提出的很多东西已经广泛地在公司得以应用。

前几天看公司培训一个项目管理的课程的时候,讲述项目的管理应该有两套团队,一个是按照职能划分的团队,类似一个“派遣公司”,一个是按照项目划分的团队,类似“创业团队”,前者负责员工培训,后者负责实际的项目为公司创收。《人月神话》“外科手术团队”的模型和这个在各个公司实际运作的机制有异曲同工之妙。

《人月神话》最主要的观点就是软件工程是一个复杂的涵盖很多方面的工作,编码只是其中非常小的一个环节,设计阶段的工作实际上是更加困难的。这一个思路也和现在 产品立项研究->架构师决定技术路线->程序员编码 的工作流程不谋而合,前两步是决定第三步走得稳不稳的设计工作,如果草率的完成将会导致第三步困难重重,举步维艰。

除此之外,模块化、增量开发……这些我们早已习以为常的东西也是作者着重论述的重点,我也无法想象前辈们在那个时代是怎样完成工作的了,是他们给我们带来了空气,就如同普罗米修斯为人类盗取了火种。