目录
这是公认的软件工程领域的神书,它不仅提到了很多我们在软件开发中陷入的思维误解,给出了我们真正需要的建议,全书的想法与思维都与实际软件开发非常贴近,而且往往能够一针见血的指出软件开发中的痛点。
书中将史前史中各种巨兽在焦油坑中垂死挣扎直至陷入坑底用来比作过去几十年的大型系统开发历程,没有那种巨兽有足够的技巧与智慧能够轻松摆脱焦油坑的束缚,而是一步步绝望的沉入坑底。过去几十年的大型系统开发,陷入坑底的团队不计其数,他们中往往都能开发出一个可运行的系统,但大部分的目标、预算、进度都远远与计划中的相悖,如果将这些个大任务分解,单个的问题往往能够轻松解决,但是这些问题纠缠在一起时,面临的挑战却远远难于我们自以为的乐观估计。
下图描述了程序转化为编程系统产品需要付出9倍的代价,而且只有编程系统产品才是真正有用的产品。
初听这个词,会认为它是神话故事或者寓言,实际人月是估计和进度安排中使用的工作量单位。作者揭示了它具有欺骗性,因为它会给我们一种感觉:时间与人力是可交换的,如果时间不够了,多加点人手就万事大吉!但是实际软件开发中可以用简化了的Brooks法则来描述这种状况:Adding mapower to a late software project makes it later. 翻译过来就是向进度落后的项目增加人手,只会使进度更加落后。
这种情况我在实际开发中也会碰到,因为新来的人手多数情况是不熟悉正在开发的系统的,首先他们需要培训,其次开发中沟通的时间也会因为新手的增多大大加长,结果如法则所言,项目进度相比于计划中产生了滞后。
如何解决? 需要提出更合理的项目进度安排。作者提供的建议是:
外科手术队伍,如书中所提供的一个研究数据:最好的和最差的表现在生产率上平均为10:1,在运行速度和空间上具有5:1的惊人差异!简言之,$20,000/年的程序员的生产率可能是$10,000/年程序员的10倍。
这样看来我们的团队应该精而小,但是根据书中计算,OS/360(一个大型系统)如果让10名非常强大的编程人员来进行开发(比一般人员各方面生产率高7倍),仍然需要10年时间,但我们知道软件行业变化太快了,10年之后这个系统会得到注意吗?不会显得过时吗?所以,如书中所言:面对真正意义上的大型系统,它太慢了。
那该如何解决了?Harlan Mills的提议提供了一个崭新的、创造性的解决方案。他建议大型项目的每一个部分由一个团队解决,该团队类似外科手术队伍,一个人完成问题的分解,其他人给予他所需要的支持,以提高效率和生产力。具体的角色分工可以参考下图:
我们可以看出平均主义、民主与平等在大型系统软件开发中不是那么起作用,我们反而看到早期英雄式编程风格的影子,外科医生承担了大部分工作,其他人成为副手,协助工作。
书中提到了很多问题,并逐一作答。下面是原文:
现在让我们来处理具有浓厚感情色彩的问题——贵族统治和民主政治。结构师难道不是新贵?他们是一些智力精英,专门来告诉可怜的实现人员如何工作?是否所有的创造性活动都被这些精英单独占有,实现人员仅仅是机器中的齿轮?难道不能遵循民主的理论,从所有的员工中搜集好的创意,以得到更好的产品,而不是将技术说明的开发工作仅限定于少数人?
最后一个问题是最简单的。我当然不认为只有结构师才有好的创意。新的概念经常来自实现人员或者用户。然而,我一直试图表达,并且我 所有的经验使我确信,系统的概念完整性决定了其使用的容易程度。不能与系统基本概念进行整合的良好想法和特色,最好放到一边,不予考虑。如果出现了很多非常重要但不兼容的构想,就应该抛弃原来的设计,对不同基本概念进行合并,在合并后的系统上重新开始。
至于贵族专制统治的问题,必须回答“是”或者“否”。就只能存在少数的结构师而言,答案是肯定的,他们的工作产物的生命周期比那些实现人员的产物要长,并且结构师一直处在解决用户问题,实现用户利益的核心地位。若要得到系统概念上的完整性,必须有人控制这些概念。这实际上是一种无需任何歉意的贵族专制统治。
第二个问题的答案是否定的,因为外部技术说明的编制工作并不比具体设计实现更富有创造性,它只是一项性质不同的创造工作而已。在给定体系结构下实现其设计,同样需要同编制技术说明一样的创造性、同样新的思路和卓越的才华。实际上,产品的成本性能比在很大程度上依靠实现人员,就如同易用性在很大程度上依赖结构师一样。
有很多行业和领域中的案例让人相信纪律和规则对行业是有益的。实际上,如同某艺术家的格言所述,“没有规矩,不成方圆。"最差的建筑往往是那些预算远远超过其实目标的项目。
通过作者的自我问答,我们可以得出结论:软件体系结构设计中,贵族专制必须实行。少数结构师决定整体框架,普通程序员是被专制对象。对于普通程序员来说,成为贵族就是其目标之一了,哈哈哈哈。
第二个系统是设计师们所设计的最危险的系统。而当他着手第三个或第四个系统时,先前的经验会相互验证,得到此类系统通用特性的判断,而且系统之间的差异会帮助他识别出经验中不够通用的部分。
对于结构师而言,如何避免这种第二个系统中的画蛇添足现象呢?他们可以为每一个小功能分配一个值:每次改进,功能x不超过m字节的内存和n微秒。这些值为作为向导警示所有人。
对于项目经理如何避免画蛇添足呢?他必须坚持至少拥有两个系统以上开发经验结构师的决定。
该章节详细介绍了拥有了形式规范、富有经验的结构师和许多编程实现人员,项目经理如何确保每个人听到、理解并实现结构师的决策呢?
巴比伦塔可能是第一个工程上的彻底失败,但它不是最后一个。交流和交流的结果——组织,是成功那个的关键。
该章通过不同的数据计算想解决一个问题:一个程序员的生产力是怎样的?
首先来看看需要的工作量:
Aron的数据:
Harr的数据:
然后根据OS/360的数据、Corbato的数据,最后得出了结论:
因此,管理上的问题不再是“是否构建一个试验性的系统,然后抛弃它? ”你必须这样做。现在的问题是:“是否预先计划抛弃原型的开发,或者是否将该原型发布给用户? ”从这个角度看待问题,答案更加清晰。将原型发布给用户,可以获得时间,但是它的代价高昂——对于用户,使用起来极度痛苦;对于重新开发的人员,分散了精力;对于产品,影响了声誉,即使最好的再设计也难以挽回名声。因此,为舍弃而计划,无论如何,你一定要这样做。
上面提到的概念即可抛弃式原型,这样的设计能够更好的面对复杂的需求与未知的变更。当然它的代价有时会非常高,所以在如今的软件开发中,它并不是必须的。在最后的总结中,会提出比它更详细,现在更适用的模型。
另外,我们经常发现一个有趣的事情,那就是随着我们对系统的不断维护,早期的维护工作所引起的漏洞修复工作反而越来越多,系统变得越来越混乱与无序,我们的每一步前进都伴随着一步后退。实际上我们的系统越来越”窄”。
书中提到了一个结论很有意思:
系统软件开发是减少混乱度(减少熵)的过程,所以它本身是处于亚稳态的。软件维护是提高混乱度(增加熵)的过程,即使是最熟练的软件维护工作,也只是放缓了系统退化到非稳态的进程。
这章用一句封面的谚语即可总结
巧匠因为他的工具而出名。(A good workman is konwn by his tools)
这章主要讲述了如何开发一个可以运行的系统?如何测试系统?如何经过测试的一系列构件集成到已测试过、可以依赖的系统?
项目怎么会被延迟整整一年的时间......延迟的时间是一天天积累下来的
上面是书中原话,这么看来对于项目组来说,一天天的进度落后即“白蚁侵蚀”往往是难发现、难防范、难处理的。而重大灾害反而容易针对性的解决。按照辩证法中提到的,这应该就是量变引起质变,每一天滞后的累积成就了灾难的爆发。
Brooks建议制定进度表,进度表的每一件事被称为“里程碑”,他们都有一个日期。而且里程碑的选择只有一个原则,必须是具体、特定、可度量的事件,而且边界明显、没有歧义。如果里程碑定得非常明确,无法自欺欺人时,很少有人就里程碑的进展弄虚作假。
什么样的文档才是好的文档?
软件开发中困难的部分是规格说明、设计和测试这些概念上的结构,而不是对概念进行表达和对实现逼真程度进行验证。
现代软件系统中这些无法规避的内在特性:复杂度、一致性、可变性和不可见性。
对于每一个特性,书中进行了详细的描述以及与其他传统行业及计算机硬件的对比,通过作者的描述,我能够清晰感觉这四种内在特性确实是软件的根本属性。
作者后面描述了许多可能的银弹,但他们大部分解决的比较高级的次要问题,仍无法解决上面提到的四个根本属性。例如面向对象编程、人工智能等,这些方法有些解决了次要问题,有些的进展却大不如人意。
文中提到的且直至今日也发挥重大作用的可能的银弹:
大多数有丰富经验的程序员拥有自己的私人开发库,可以使他们使用大约30%的重用代码来开发软件。公司级别的重用能提供70%的重用代码量,它需要特殊的开发库和管理支持。公司级别的重用代码也意味着需要对项目中的变更进行统计和度量,从而提高重用的可信程度。
重用是一件说起来容易,做起来难的事情。它同时需要良好的设计和文档。即使我们看到了并不十分常见的优秀设计,但如果没有好的文档,我们也不会看到能重用的构件。
有哪些在写作时就正确,现在仍然成立的。还有哪些现在看来是错误的了?
用该章的最后一段话作结尾: