阅读经典——《人月神话》06
人狼传说
在所有恐怖民间传说的妖怪中,最可怕的是人狼,因为它们可以完全出乎意料地从熟悉的面孔变成可怕的怪物。为了对付人狼,我们在寻找可以消灭它们的银弹。
软件项目具有一些人狼的特性,常常看似简单明了的东西,却有可能变成一个落后进度、超出预算、存在大量缺陷的怪物。因此,我们听到了近乎绝望的寻求银弹的呼唤,寻求一种可以使软件成本像计算机硬件成本一样迅速降低的尚方宝剑。
但是,从近十年来的情况来看,没有发现银弹的踪迹。本文我们试图通过分析软件问题的本质来探究其原因。
软件工程中的根本和次要问题
没有任何一种单纯的技术或管理上的进步,能够独立地承诺在十年内大幅度地提高生产率、可靠性和简洁性。
作者为什么敢这样说?
因为作者把软件活动的任务分为两类:根本任务——打造构成抽象软件实体的复杂概念结构,次要任务——使用编程语言表达这些抽象实体,在空间和时间限制内将它们映射成机器语言。
后者随着计算机软件技术的日新月异,使用高级编程语言以及更智能的工具,已经获得了大幅度的改善。但前者却不可能在十年内有大幅度的提高。因此从总体上来看,除非次要任务占到了所有任务的9/10,否则即使次要任务的时间缩短到零,也不会带来生产率数量级上的提高。
因此,是时候关注软件工程中的根本问题了。
根本问题为什么那么困难?
为什么软件的发展速度让我们难以满意?因为在三十年间,计算机硬件取得了6个数量级的提高,这是有史以来任何产业都未曾经历过的辉煌。相比之下,软件就逊色多了。
根本问题是软件特性中的固有困难,也就是说,无论技术如何变化,只要是软件产品,一定存在这样的问题。换句话说,根本问题是始终存在的,无论它以何种方式体现,无论它在哪个阶段出现。听起来类似高中物理中的能量守恒定律。
说的有些邪乎,现在让我们看看这些根本问题到底是什么。
复杂度
软件实体可能比任何由人类创造的其他实体更复杂,因为没有任何两个软件部分是相同的(至少在语句的级别上)。(如果有相同的情况,我们会把它们合并成供调用的子函数。)在这一方面,软件系统与计算机、建筑或者汽车大不相同,后者往往存在着大量重复的部分。
软件在扩展的过程中不同元素间的交互以指数的速度递增,导致整个软件的复杂度剧增。
需要强调的是,软件的复杂度是根本属性,不是次要因素。数学和物理学在过去的三个世纪取得了巨大的进步,数学家和物理学家们为复杂的现象建立了简化的模型,从模型中抽取各种特性,并通过实验来验证这些特性。这些方法之所以可行,是因为模型中忽略的复杂度不是被研究现象的根本属性。当复杂度是本质属性时,这些方法就行不通了。
复杂性的存在使软件开发变得异常困难,从团队管理到代码编写,无处不受复杂性的影响。
一致性
大多数情况下,或为了遵循标准,或为了保持兼容,软件需要保持对接口的一致性。一旦前人的设计已成定局,后来人对软件的任何再设计,都无法简化这些复杂特性。
可变性
软件修改的低成本也带来了可变性这一不好的结果。汽车、建筑一旦出厂之后不会经常发生修改,因为修改的成本很高,从而打消了那些想提出修改的人的念头。而软件的功能很容易被用户感知并提出修改意见。
所有优秀的软件都会发生变更。如果一款软件受到众多用户喜爱,它必然要伴随着快速的更新迭代。而且它的生命会远远长于计算机硬件。即使不是更换计算机,也有可能是更换新型号的磁盘、显示器或打印机。因此软件必须与各种新生事物保持一致,所有外界变化无情地强迫着软件也随之变化。
不可见性
软件无法可视化。我们无法像建筑平面图、分子结构图一样把软件结构用某种空间形态表示出来。当我们试图这样做时,会发现它包含了太多相互关联的结构,根本无法用少量维度的层次结构表示出来。这一缺憾严重限制了软件的设计过程,也严重阻碍了思路之间的交流。
寻找银弹的尝试
近年来在软件领域中产生的新技术或新工具,似乎让我们隐约看到了银弹的希望。
高级编程语言、分时操作系统、集成开发环境,这是软件领域取得的最富有成效的三次进步。每一次都解决了软件构建上的巨大困难,但可惜的是,这些都是次要困难,不是本质困难。
具有成为银弹的潜力的一些技术,Ada和其它高级编程语言、面向对象编程、人工智能、专家系统、“自动编程”、图形化编程、程序验证、更好的环境和工具、工作站等等。在作者看来,它们从各个方面解决了软件工程中的一些问题,但仍然看不到解决根本问题的希望。
颇具前途的方法
我们需要着眼于解决软件上的必要困难——即准确地表达复杂概念结构。幸运的是,下面这些方案就颇具前途。
购买而非自行开发
构建软件最可能的彻底解决方案是不开发任何软件。
如果有通用软件可以满足需求,购买它们是最节约成本的方法。并且它们往往配备了书写良好的文档,在某种程度上比自行开发的软件维护得更加完备。
软件成本完全是开发的成本而非复制的成本,因此即使在少数用户之间共享,也能很大程度上降低每个用户的成本。
需求精炼和快速原型
开发软件系统最困难的部分是确定详细的需求,包括所有的人机界面、与机器和其它软件系统的接口。
糟糕的是,客户往往不知道自己需要什么,他们也不知道哪些问题是必须回答的,并且,连必须确定的细节也常常根本不予考虑,甚至只是简单地回答——“开发一个类似于我们已有的手工信息处理过程的新软件系统”。然而,到了实际交付使用时,客户又会指出其中的设计错误,抱怨为什么开发的系统不是他们想要的。
因此,在计划任何软件活动时,要让客户和设计人员进行多次广泛的交流沟通,这是非常必要的。
但是,这里不得不下一个悲观的定论。即使客户和工程师做了充分商讨,想要完整、精确、正确地抽取现代软件产品的需求也都是不可能的。
所以,在技术上最有希望的,并且能够解决软件的根本而非次要问题的技术,是开发快速原型化系统的方法和工具,以作为迭代需求过程的一部分。
快速原型是指把客户需求迅速用接近实际软件产品的效果演示出来,向客户确认软件的界面和功能是否正确理解,并且在开发过程中反复确认。
增量开发
软件应该逐步完善,而非一次性搭建完成。增量式的开发过程对团队士气的提升大有好处。
卓越的设计人员
卓越设计来自于卓越的开发人员。软件开发是一个创造性的过程,卓越和一般之间的差异接近于一个数量级。
那些优秀的大型项目虽然由许多人共同开发,但这些激动人心的产品往往是一个或少数伟大设计师们的思想成果。
许多软件机构花费了大量时间和精力来寻找和培养管理人员,却不在杰出的设计人员身上投入相同的资源,然而产品的技术特色最终依赖于这些设计人员。
所以,建议每个软件机构作出决定并表明立场:杰出的设计人员和卓越的管理人员同样重要,他们应该得到相同的培养和回报。不仅仅是薪资,还包括各个方面的认可——办公室规模、家具、个人的设备、差旅费用、人员支持等,必须完全一致。
总之,目前为止还没有真正的银弹,但软件工程的发展仍然会朝着好的方向努力,让我们拭目以待。
注:本文参考《人月神话》作者Brooks于1986年发表的文章《没有银弹——软件工程中的根本问题和次要问题》。时间已经过去30年,文中的思想却仍然熠熠生辉。