展,但在现实的软件领域中,既有大量优秀的工作,也有不引人注意的平稳进步。- 113 ------------------------ Page 126-----------------------所有针对软件开发过程中次要困难的技术工作基本上能表达成以下的生产率公式:任务时间 = ∑(频率)×(时间)i i如果和我所认为的一样,工作的创造性部分占据了大部分时间,那么那些仅仅是表达概念的活动并不能在很大程度上影响生产率。因此,我们必须考虑那些解决软件上必要困难的活动——即,准确地表达复杂概念结构。幸运的是,其中的一些非常有希望。购买和自行开发。构建软件最可能的彻底解决方案是不开发任何软件。情况每一天都有些好转,越来越多的软件提供商,为各种眼花缭乱的应用程序提供了质量更好、数量更多的软件产品。当我们的软件工程师正忙于生产方法学时,个人计算机的惊天动地的变化为软件创造了广阔的市场。每个报摊上都有大量的月刊,根据机器的类型,刊登着从几美元到几百美元的各种产品的广告和评论。更多专业厂商为工作站和UNIX 市场提供了很多非常有竞争力的产品,甚至很多工具软件和开发环境软件都可以随时购买使用。对于独立的软件模块市场,我已在其他的地方提出一些建议。以上提到的任何软件,购买都要比重新开发要低廉一些。即使支付100,000 美元,购买的软件也仅仅是一个人年的成本。而且软件是立即可用的!至少对于现有的产品、对于那些专注于该领域开发者的成果而言,它们是可以立刻投入使用的。并且,它们往往配备了书写良好的文档,在某种程度上比自行开发的软件维护得更加完备。我相信,这个大众市场将是软件工程领域意义最深远的开发方向。软件成本一直是开发的成本,而不是复制的成本。所以,即使只在少数使用者之间实现共享,也能在很大程度上减少成本。另一种看法是使用软件系统的n 个拷贝,将会使开发人员的生产率有效地提高n 倍。这是一个领域和行业范围的提高。当然,关键的问题还是可用性。是否可以在自己的开发工作中使用商用的软件包?这里,有一个令人吃惊的问题。在1950~1960 年期间,一个接一个的研究显示,用户不会在工资系统、物流控制、帐务处理等系统中使用商用软件包。需求往往过于专业,不同情况之间的差别太大。在80 年代,我们发现这些软件包的需求大为增加,并得到了大规模的使用。什么导致了这样的变化?并不是软件包发生了变化。它们可能比以前更加通用和更加客户化一些,但并不太多。- 114 ------------------------ Page 127-----------------------同样,也不是应用发生了变化。即使有,今天的商业和学术上的需要也比20 年以前更加不同和复杂。重大的变化在于计算机硬件/软件成本比率。在1960 年,2 百万美元机器的购买者觉得他可以为定制的薪资系统支付250,000 美元。现在,对50,000 美元的办公室机器购买者而言,很难想象能为定制薪资系统再支付费用。因此,他们把上述系统的模块进行调整,添加到可用的软件包中。计算机现在如此的普遍,上述的改编和调整是发展的必然结果。我的上述观点也存在一些戏剧性的例外——软件包的通用化方面并没有发生什么变化,除了电子表格和简单的数据库系统。这些强大的工具,出现得如此之晚和如此醒目,导致无数应用中的一些并不十分规范。大量的文章、甚至书籍讲述了如何使用电子表格应付很多意想不到的问题。原先作为客户程序,使用Cobol或者报表生成程序编写的大量应用,如今已经被这些工具所取代。现在很多用户天天操作计算机,使用着各种各样的应用程序,但并不编写代码。事实上,他们中间很多人无法为自己的计算机编写任何程序,不过他们非常熟练地使用计算机来解决新问题。我认为,对于现在的很多组织机构来说,最有效的软件生产率策略是在生产一线配备很多个人计算机,安装好通用的书写、作图、文件管理和电子表格程序,以及配备能熟练使用它们的人员,并且把这些人员散布到各个岗位。类似的策略——通用的数学和统计软件包,以及一些简单的编程能力,同样地适用于很多实验室的科学工作者。需求精炼和快速原型。开发软件系统的过程中,最困难的部分是确切地决定搭建什么样的系统。概念性工作中,没有其他任何一个部分比确定详细的技术需求更加困难,详细的需求包括了所有的人机界面、与机器和其他软件系统的接口。需求工作对系统的影响比其他任何一个部分的失误都大,当然纠正需求的困难也比其他任何一个部分要大。因此,软件开发人员为客户所承担的最重要的职能是不断重复地抽取和细化产品的需求。事实上,客户不知道他们自己需要什么。他们通常不知道哪些问题是必须回答的。并且,连必须确定的问题细节常常根本不予考虑,甚至只是简单地回答——“开发一个类似于我们已有的手工处理过程的新软件系统”——实际上都过于简单。客户决不会仅仅要求这些。复杂的软件系统往往是活动的、变化的系统。活动的动态部分是很难想象的。所以,在计划任何软件活动时,要让客户和设计人员之间进行多次广泛的交流沟通,并将其作为系统定义的- 115 ------------------------ Page 128-----------------------一部分。这是非常必要的。这里,我将向前多走一步,下一个定论。在尝试和开发一些客户定制的系统之前,即使他们和软件工程师一起工作,想要完整、精确、正确地抽取现代软件产品的需求——这,实际上也是不可能的。因此,现在的技术中最有希望的,并且解决了软件的根本而非次要问题的技术,是开发作为迭代需求过程的一部分——快速原型化系统的方法和工具。软件系统的快速原型对重要的系统界面进行模拟,并演示待开发系统的主要功能。原型不必受到相同硬件速度、规模或者成本约束的限制。原型通常展示了应用程序的功能主线,但不处理任何如无效输入、退出清除等异常情况。原型的目的是明确实际的概念结构,从而客户可以测试一致性和可用性。现在的软件开发流程基于如下的假设——事先明确地阐述系统,为系统开发竞标,实际进行开发,最后安装。我认为这种假设根本上就是不正确的,很多软件问题就来自这种谬误。因此,如果不进行彻底地调整,就无法消除那些软件问题。其中,一种改进是对产品和原型不断往复地开发和规格化。增量开发——增长,而非搭建系统。我现在还记得在1958年,当听到一个朋友提及搭建(building),而不是编写(writing)系统时,我所感受到的震动。一瞬间,我的整个软件开发流程的视野开阔了。这种暗喻是非常有力和精确的。现在,我们已经理解软件开发是如何类似于其他的建造过程,并开始随意地使用其他的暗喻,如规格说明、构件装备、脚手架(测试平台)(specifications, assembly of components, and scaffolding)。暗喻“搭建系统”的使用已经有些超出了它的有效期限,是重新换一种表达方式的时候了。如果现在的开发情况和我考虑的一样,那些概念性的结构非常复杂,以致于难以事先精确地说明和零缺陷地开发,那么我们必须采用彻底不同的方法。让我们转向自然界,研究一下生物的复杂性,而不是人们的僵硬工作。我们会发现它们的复杂程度令我们敬畏。光是大脑本身,就比任何对它的描述都要复杂,比任何的模拟仿真都要强大,它的多样性、自我保护和自我更新能力异常丰富和有力。其中的秘密就是逐步发育成长,而不是一次性搭建。所以,我们的软件系统也必须如此。很多年前,HarlanMill建议所有软件系统都应该- 116 ------------------------ Page 129-----------------------11以增量的方式开发 。即,首先系统应该能够运行,即使未完成任何有用功能,只能正确调用一系列伪子系统。接着,系统一点一点被充实,子系统轮流被开发,或者是在更低的层次调用程序、模块、子系统的占位符(伪程序)等。从我在软件工程试验班上开始推动这种方法起,其效果不可思议。在过去几十年中,没有任何方法和技术能如此彻底地改变我自己的实践。这种方法迫切地要求自顶向下设计,因为它本身是一种自顶向下增长的软件。增量化开发使逆向跟踪很方便,并非常容易进行原型开发。每一项新增功能,以及针对更加复杂数据或情况的新模块,从已经规划的系统中有机地增长。这种开发模式对士气的推动是令人震惊的。当一个可运行系统——即使是非常简单的系统出现时,开发人员的热情就迸发了出来。当一个新图形软件系统的第一副图案出现在屏幕上时,即使是一个简单的长方形,工作的动力也会成倍地增长。在开发过程中的每个阶段,总有可运行的系统。我发现开发团队可以在四个月内,培育(grow)出比搭建(building)复杂得多的系统。大型项目同样可以得到与我所参与的小型项目相同的好处12。卓越的设计人员。关键的问题是如何提高软件行业的核心,一如既往的是——人员。我们可以通过遵循优秀而不是拙劣的实践,来得到良好的设计。优秀的设计是可以传授的。程序员的周围往往是最出色的人员,因此他们可以学习到良好的实践。因此,美国的重大策略是颁布各种优秀的现代实践。新课程、新文献。象软件工程研究所SEI等新机构的出现都是为了把我们的实践从不足提升到更高的水平。其正确性是勿庸置疑的。不过,我不认为我们可以用相同的方式取得下一次进步。低劣设计和良好设计之间的区别可能在于设计方法中的完善性,而良好设计和卓越设计之间的区别肯定不是如此。卓越设计来自卓越的设计人员。软件开发是一个创造性的过程。完备的方法学可以培养和释放创造性的思维,但它无法孕育或激发创造性的过程。其中的差异并不小——就象萨列里和莫扎特。一个接一个的研究显示,非常卓越的设计者产生的成果更快、更小、更简单、更优雅,实现的代价更少。卓越和一般之间的差异接近于一个数量级。简单地回顾一下,尽管很多杰出、实用的软件系统是由很多人共同设计开发,但是那- 117 ------------------------ Page 130-----------------------些激动人心、拥有广大热情爱好者的产品往往是一个或者少数伟大设计师们的思想。考虑一下Unix、APL、Pascal、Modula、Smalltalk 的界面、甚至Fortran;与之对应的产品是Cobol、PL/I、Algol、MVS/370 和MS/DOS (图6.1)。YES NOUnix CobolAPL PL/IPascal AlgolModula MVS/370Smalltalk MS-DOSFortran图16.1:激动人心的产品因此,尽管我强烈地支持现在的技术转移和开发技能的传授,但我认为我们可以着手的最重要工作是寻求培养卓越设计人员的途径。没有任何软件机构可以忽视这项挑战。尽管公司可能缺少良好的管理人员,但决不会比良好设计人员的需求更加迫切,而卓越的管理人员和设计人员都是非常缺乏的。大多数机构花费了大量的时间和精力来寻找和培养管理人员,但据我所知,它们中间没有任何的一家在寻求和培育杰出的设计人员上投入相同的资源,而产品的技术特色最终依赖于这些设计人员。我的第一项建议是每个软件机构必须决定和表明,杰出的设计人员和卓越的管理人员一样重要,他们应该得到相同的培养和回报。不仅仅是薪资,还包括各个方面的认可——办公室规模、安排、个人的设备、差旅费用、人员支持等——必须完全一致。如何培养杰出的设计人员?限于篇幅,不允许进行较长的介绍,但有些步骤是显而易见的。尽可能早地、有系统地识别顶级的设计人员。最好的通常不是那些最有经验的人员。为设计人员指派一位职业导师,负责他们技术方面的成长,仔细地为他们规划职业生涯。为每个方面制订和维护一份职业计划,包括与设计大师的、经过仔细挑选的学习过程、正式的高级教育和以及短期的课程——所有这些都穿插在设计和技术领导能力的培养安排中。- 118 ------------------------ Page 131-----------------------为成长中的设计人员提供相互交流和学习的机会。- 119 ------------------------ Page 132-----------------------再论《没有银弹》 (“No Silver Bullet ”Refired)生死有命,富贵在天- 威廉三世,奥伦治王子那些想看到完美方案的人,其实在心底里就认为它们以前不存在,以后也不可能出现。- 亚历山大·波普,批判散文Every bullet has its billet.- WILLIAM III OF ENGLAND, PRINCE OF ORANGEWhoever thinks a faultless piece to see, thinks what ne’er was, nor e’er shall be.- ALEXANDER POPE, AN ESSAY ON CRITISIM人狼和其他恐怖传说《没有银弹-软件工程中的根本和次要问题》(第16章)最初是在IFIP’86 年都柏林大会的约稿,接着在一系列的刊物上发表1。《计算机》杂志上翻印了该文章,封面是一副类2伦敦人狼》影片的恐怖剧照。同时,还有一栏补充报道《杀死人狼》,描述了银弹将似于《要完成的(现代)神话。在出版以前,我并未注意到补充报道和文字,也没有料到一篇严肃的技术性文字会被这样润色。Computer 杂志的编辑们是取得他们想要的效果的专家,不过,似乎有很多人阅读了那篇文章。因此,我为那一章选择了另一幅人狼插图,一幅对这种近乎滑稽物种的古老素描。我希望这副并不刺眼的图案有相同的正面效果。- 120 ------------------------ Page 133-----------------------存在着银弹-就在这里!《没有银弹》中声称和断定,在近十年内,没有任何单独的软件工程进展可以使软件生产率有数量级的提高(引自1986年的版本)。现在已经是第九个年头,因此也该看看是否这些预言得到了应验。《人月神话》一文被大量地引用,很少存在异议;相比之下,《没有银弹》却引发了众多的辩论,编辑收到了很多文章和信件,至今还在延续3。他们中的大多数攻击其核心论点和我的观点——没有神话般的解决方案,以及将来也不会有。他们大都同意《没有银弹》一文中的多数观点,但接着断定实际存在着杀死软件怪兽的银弹——由他们所发明的银弹。今天,当我重新阅读一些早期的反馈,我不禁发现在1986 年~1987 年期间,曾被强烈推崇的秘方并没有出现所声称的戏剧性效果。在购买计算机软件和硬件时,我喜欢听取那些真正使用过产品并感到满意的用户的推荐。类似的,我很乐意接受银弹已经出现的观点,例如,某个名副其实的中立客户走到面前,并声称,“我使用了这种方法、工具或者产品,它使我的软件生产率提高了十倍。”很多书信作者进行了若干正确的修订和澄清,其中一些还提供了很有针对性的分析和辩驳,对此我非常感激。本章中,我将同大家分享这些改进,以及对反面意见进行讨论。含糊的表达将会导致误解某些作者指出我没有将一些观点表达清楚。次要(Accident)。在第 16 章的摘要中,我已经尽我所能地清晰表达了《没有银弹》一文的主要观点。然而,仍有些观点由于术语“accident (偶然)”和“accidental (次要)”4而被混淆,这些术语来自亚里斯多德的古老用法 。术语“accidental”,我不是指“偶然发生”,也不是指“不幸的”,而是更接近于“附带的”或者“从属的”。我并不是贬低软件构建中的次要部分,相反,我认同英国剧作家、侦探小说作者和神学家桃乐丝·赛尔丝看待创造性活动的观点,创造性活动包括(1)概念性结构的形式规格化,(2)使用现实的介质来实现,(3)在实际的使用中,与用户交互5。在软件开发中,我称为“必要 (essence)”的部分是构思这些概念上的结构;我称为“次要(accident)”的