上周逛山西路军人俱乐部,偶然看见《人月神话》40周年中文纪念版,翻了几页感觉不错,就买回来看看。记得大学时老师推荐过,一晃过去了十年,工作也有八年了,如果是刚毕业或只做几个人的小项目时读这书跟做过几个数十人到数百人的项目之后再读感觉肯定大不同。书的开头就说明这里谈的是大型系统的开发,如果一直是几个人的小团队看到书里的论述或许会觉得匪夷所思。主要内容实际才二百多页,却经常有闪光的格言警句给予你阅读时的快感,这里首先摘录一些:
表面上看起来好像没有任何一个单独的问题会导致困难,每个问题都能获得解决,但是当它们相互纠缠和累积在一起的时候,团队的行动就会变得越来越慢。(第1章 焦油坑)
对于系统编程人员而言,对其他人的依赖是一件非常痛苦的事情。他依靠其他人的程序,而这些程序往往设计的并不合理、实现拙劣、发布不完整或者文档记录得很糟。(第1章 焦油坑)
对于创造者,只有在实现的过程中,才能发现我们构思的不完整性和不一致性。(第2章 人月神话)
用人月作为衡量一项工作的规模是一个危险和带有欺骗性的神话。它暗示着人员数量和时间是可以相互替换的。人数和时间的互换仅仅适用于以下情况:某个任务可以分解给参与人员,并且他们之间不需要相互的交流(第2章 人月神话)
向进度落后的项目中增加人手,只会使进度更加落后。这就是除去了神话色彩的人月。项目的时间依赖于顺序上的限制,人员的最大数量依赖于独立子任务的数量。(第2章 人月神话)
对于计算机系统而言,尽管它们通常没有花费几个世纪的时间来构建,但绝大多数系统体现出的概念差异和不一致性远远超过欧洲的大教堂。这通常并不是因为它由不同时代的设计师开发,而是由于设计被分成了由若干人完成的若干任务。我主张,在系统设计中,概念完整性应该是最重要的考虑因素。(第4章 贵族专制、民主政治和系统设计)
概念的完整性要求设计必须由一个人,或者非常少数互有默契的人员来实现。而进度压力却要求很多人员来开发系统。(第4章 贵族专制、民主政治和系统设计)
设计师将709的操作集合设计得如此丰富和充沛,以至于只有一半操作被客户经常使用。(第5章 画蛇添足)
任何管理任务的关注焦点都是时间、地点、人员、项目内容和资金。(第10章 提纲挈领)
新的系统概念或新技术会不断出现,必须构建一个用来抛弃的系统,因为即使是最优秀的项目经理,也不能无所不知地在最开始解决这些问题。抛弃原型概念本身就是对事实的接受——随着学习的过程更改设计。(第11章 未雨绸缪)
实际上,重大灾害是比较容易处理的,它往往和重大的压力、彻底的重组、新技术的出现有关,整个项目组通常可以应付自如。当时一天一天的进度落后是难以识别、不容依法防范和难以弥补的。(第14章 祸起萧墙)
记忆衰退的规律会使用户——作者失去对程序的了解,于是他不得不重拾自己劳动的细节。(第15章 另外一面)
当然,我认为全书最精华的部分其实是第16章 人月神话,因为它把这些年我的隐约的感觉用精炼又充满思辨的语言表达出来,不要忘记,这是在40年前。这里简述一下该章的论证思路:
1.所有软件活动可以分成两种任务:根本任务和次要任务,根本任务是打造构成抽象软件实体的复杂概念结构,次要任务是使用编程语言表达这些抽象实体,在空间和时间限制下将它们映射成机器语言。
2.所谓根本(essence)是指软件特性中的固有的困难,所谓次要(accident)是指出现在目前的生产中,但并非与生俱来的困难。那为什么构造异常复杂的抽象概念结构是根本问题呢?这里涉及现代软件系统中的几个无法规避的内在特性:复杂度、一致性、可变性和不可见性。
复杂度:计算机存在很多种状态,这使得构思、描述和测试都非常困难。软件系统的状态又比计算机的状态多若干个数量级。同样,软件实体的扩展也不仅仅是相同元素的重复添加,而必须是不同元素实体的添加。大多数情况下,这些元素以非线性递增的方式交互,因此整个软件复杂度要比非线性增长多得多。
一致性:物理学家坚信,必定存在着某种通用原理,或者在夸克中,或者在统一场论中。软件工程师却无法从类似的信念中获得安慰,他必须掌握的很多复杂度是随心所欲、毫无规则可言的,来自若干必须遵循的人为惯例和系统。许多情况下,因为是开发最新的软件,它必须遵循各种接口。另一些情况下,软件的开发目标就是兼容性。所以很多复杂性来自保持与其他借口的一致性,对软件的任何再设计,都无法简化这些复杂特性。
可变性:软件实体经常会遭受到持续的变更压力。部分原因是系统中的软件包含了很多功能,而功能是最容易感受到变更压力的部分。另外的原因是软件可以很容易地进行修改——它是纯粹思维活动的产物,可以无限扩展。简言之,软件产品扎根于文化的母体中,如各种应用、用户、自然及社会规律、计算机硬件等。后者持续不断的变化着,这些变化无情地强迫着软件也随之变化。
不可见性:软件的客观存在不具有空间的形体特征。当我们试图用图形来描述软件结构时,发现它是很多相互关联、重叠在一起的图形。这些图形可能代表控制流程、数据流、依赖关系、时间序列和名字空间的相互关系等。在上述结构上建立的概念控制的一种方法是强制将关联分割,直到可以层次化一个或多个图形。除去软件结构上的限制和简化方面的进展,软件仍然保持着无法可视化的固有特性,从而剥夺了一些具有强大功能的概念工具的构造创意。
3.基于第2点描述的根本问题,现有(这里的现在指的是40年前)的高级语言、面向对象编程、人工智能、“自动”编程、图形化编程、更好的编程开发环境和工具等等都只是在解决次要困难上的一些突破。即这些进步都是解决软件构建上的巨大困难之术,所有针对软件开发过程中次要困难的技术工作基本上能表达成以下生存率公式:
任务时间=∑(频率)*(时间)
而工作的创造性部分占据了大部分时间,那些仅仅是表达概念的活动并不能在很大程度上影响生存率。
4.因此,必须考虑那些解决软件上必要困难的活动——准确的表达复杂概念结构。这里作者给出了一些当时认为的有希望的办法:购买软件提供商的产品、需求精炼和快速原型、增量开发、卓越的设计人员。
以上是我所认为的全书之精华论述,四十年后再看还是熠熠生辉,其间计算机硬件性能的提升诚如摩尔定律所言,而软件开发的生存率却远达不到这般飞速,原因正是如上所说之大型软件工程中的根本问题。