# 第 17 章 再论《没有银弹》 ("No Silver Bullet"Refired)
生死有命,富贵在天
——威廉三世,奥伦治王子
那些想看到完美方案的人,其实在心底里就认为它们以前不存在,以后也不可能出现。
——亚历山大·波普,批判散文
Every bullet has its billet.
——WILLIAM III OF ENGLAND, PRINCE OF ORANGE
Whoever 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 杂志的编辑们是取得他们想要的效果的专家,不过,似乎有很多人阅读了那篇文章。因此,我为那一章选择了另一幅人狼插图,一幅对这种近乎滑稽物种的古老素描。我希望这副并不刺眼的图案有相同的正面效果。
# 存在着银弹-就在这里!
《没有银弹》中声称和断定,在近十年内,没有任何单独的软件工程进展可以使软件生产率有数量级的提高(引自 1986 年的版本)。现在已经是第九个年头,因此也该看看是否这些预言得到了应验。
《人月神话》一文被大量地引用,很少存在异议;相比之下,《没有银弹》却引发了众多的辩论,编辑收到了很多文章和信件,至今还在延续 3。他们中的大多数攻击其核心论点和我的观点——没有神话般的解决方案,以及将来也不会有。他们大都同意《没有银弹》一文中的多数观点,但接着断定实际存在着杀死软件怪兽的银弹——由他们所发明的银弹。今天,当我重新阅读一些早期的反馈,我不禁发现在 1986 年~ 1987 年期间,曾被强烈推崇的秘方并没有出现所声称的戏剧性效果。
在购买计算机软件和硬件时,我喜欢听取那些真正使用过产品并感到满意的用户的推荐。类似的,我很乐意接受银弹已经出现的观点,例如,某个名副其实的中立客户走到面前,并声称,"我使用了这种方法、工具或者产品,它使我的软件生产率提高了十倍。"
很多书信作者进行了若干正确的修订和澄清,其中一些还提供了很有针对性的分析和辩驳,对此我非常感激。本章中,我将同大家分享这些改进,以及对反面意见进行讨论。
# 含糊的表达将会导致误解
某些作者指出我没有将一些观点表达清楚。
次要(Accident)。在第 16 章的摘要中,我已经尽我所能地清晰表达了《没有银弹》一文的主要观点。然而,仍有些观点由于术语"accident(偶然)"和"accidental(次要)"而被混淆,这些术语来自亚里斯多德的古老用法。术语"accidental",我不是指"偶然发生",也不是指"不幸的",而是更接近于"附带的"或者"从属的"。
我并不是贬低软件构建中的次要部分,相反,我认同英国剧作家、侦探小说作者和神学家桃乐丝·赛尔丝看待创造性活动的观点,创造性活动包括(1)概念性结构的形式规格化,(2)使用现实的介质来实现,(3)在实际的使用中,与用户交互。在软件开发中,我称为"必要(essence)"的部分是构思这些概念上的结构;我称为"次要(accident)"的部分指它的实现过程。
现实问题。对我而言(尽管不是所有人),关键论点的正确与否归结为一个现实问题:整个软件开发工作中的哪些部分与概念性结构的精确和有序表达相关,哪些部分是创造那些结构的思维活动?根据缺陷是概念性的(例如未能识别某些异常),或者是表达上的问题(例如指针错误或者内存分配错误)等,可以将这些缺陷的寻找和修复工作进行相应的划分。
在我看来,开发的次要或者表达部分现在已经下降到整个工作的一半或一半以下。由于这部分是现实的问题,所以原则上可以应用测量技术来研究。这样,我的观点也可以通过来更科学和更新的估计来纠正。值得注意的是,还没有人公开发表或者写信告诉我,次要部分的任务占据了工作的 9/10。
《没有银弹》无可争辩地指出,如果开发的次要部分少于整个工作的 9/10,那么即使不占用任何时间(除非出现奇迹),也不会给生产率带来数量级的提高。因此,必须着手解决开发的根本问题。
由于《没有银弹》,Bruce Blum 把我的注意力引向 Herzberg、Mausner 和 Sayderman 等人在 1959 年的研究。他们发现动机因素可以提高生产率。另一方面,环境和次要因素,无论起到多么积极的作用,仍无法提高生产率。但是在产生负面影响时,它们会使生产率降低。《没有银弹》认为很多软件开发过程已经消除了以下负面因素:十分笨拙的机器语言、漫长的批处理周转时间以及无法忍受的内存限制。
因为是根本困难所以没有希望?1990 年 Brad Cox 的一篇非常出色的论文《这就是银弹》(There Is a Silver Bullet),有说服力地指出重用和交互的构件开发是解决软件根本困难的一种方法。我由衷地表示赞同。
不过,Cox 在两点上误解了《没有银弹》。首先,他断定软件困难来自"编程人员缺乏构建当今软件的技术"。而我认为根本困难是固有的概念复杂性,无论是任何时间,使用任何方法设计和实现软件的功能,它都存在。其次,他(以及其他人)阅读《没有银弹》,并认定文中的观点是没有任何处理软件开发中根本困难的希望——这不是我的本意。作为本质上的困难,构思软件概念性的结构本身就有复杂性、一致性、可变性及不可见性的特点。不过实际上,每一种困难产生的麻烦都是可以改善的。
复杂性是层次化的。例如,复杂性是最严重的内在困难,并不是所有的复杂性都是不可避免的。我们的很多软件,但不是全部,来自应用本身随意的复杂特性。来自一家国际管理咨询公司,MYSIGMA Lars Sodahl 的 Lars Sodahl 和合作伙伴曾写道:
就我的经验而言,在系统工作中所遇到的大多数困难是组织结构上的一些失误征兆。试图为这些现实建模,建立同等复杂的程序,实际上是隐藏,而不是解决这些杂乱无章的情况。
Northrop 的 Steve Lukasik 认为即使是组织机构上的复杂性也不是任意的,可能容易受到策略调整的影响。
我曾作为物理学家接受过培训,因此倾向于用更简单的概念来描述"复杂"事物。现在你可能是正确的,我无法断定所有的复杂事物都容易用有序的规律表达..同样的道理,你不能断定它们不能。
..昨天的复杂性是今天的规律。分子的无序性启迪了气体动力学理论和热力学的三大定律。现在,软件没有揭示类似的规律性原理,但是解释为什么没有的重担在你的身上。我不是迟钝和好辩的。我相信有一天软件的"复杂性"将以某种更高级的规律性概念来表达(就像物理学家的不变式)。
我并没有着手于 Lukasik 提倡的更深层次的分析。作为一个学科,我们需要更广泛的信息理论,它能够量化静态结构的信息内容,就像针对交互流的香农信息论一样。这已经超越了我的能力。作为对 Lukasik 的简单回应,我认为系统复杂性是无数细节的函数,这些细节必须精确而且详细地说明——或者是借助某种通用规则,或者是逐一阐述,但决不仅仅是统计说明。仅靠若干人不相干的工作,是不大可能产生足够的一致性,能用通用规律进行精确描述。
不过,很多复杂性并不完全是因为和外部世界保持一致,而是因为实现的本身,例如数据结构、算法、互联性等。而在更高的级别开发(发展)软件,使用其他人的成果,或者重用自己的程序——都能避免面对整个层次的复杂性。《没有银弹》提出了全力解决复杂性问题的方法,这种方法可以在现实中取得十分乐观的进展。它倡导向软件系统增加必要的复杂性:
- 层次化,通过分层的模块或者对象。
- 增量化,从而系统可以持续地运行。
# Harel 的分析
David Harel,在 1992 年的论文《批评银弹》(Biting the Silver Bullet)中,对已出版的《没有银弹》进行了很多最仔细的分析。
悲观主义 vs. 乐观主义 vs. 现实主义。Harel 同时阅读了《没有银弹》和 1984 年 Parnas 的文章《战略防卫系统的软件问题》(Software Aspects of Strategic Defense Systems),认为它们"太过黯淡"。因此,他试图在论文《走向系统开发的光明未来》(Toward a Brighter Future for System Development)中展现其明亮的一面。Cox 同 Halel 一样认为《没有银弹》一文过于悲观,从而他提出"但是,如果从一个新视点去观察相同的事情,你会得到一个更加乐观的结论"。他们的论调都有些问题。
首先,我的妻子、同事和我的编辑发现我犯乐观主义错误的几率远远大于悲观主义。
毕竟,我的从业背景是程序员,乐观主义是这个行业的职业病。
《没有银弹》一文明确地指出"我们看看近十年来的情况,没有银弹的踪迹..怀疑论者并不是悲观主义者..虽然没有通天大道,但是路就在脚下。"它预言了如果 1986 年的很多创新能持续开拓和发展,那么实际上它们的共同作用能使生产率获得数量级的提高。随着 1986 ~ 1996 十年过去了,这个预言即使说明了什么,那也是过于乐观,而不是过于悲观。
就算《没有银弹》总体看来有些悲观,那么到底存在什么问题?是否爱因斯坦关于任何物体运动的速度无法超过光速的论断过于"黯淡"或者"令人沮丧"呢?那么哥德尔关于某些事物无法计算的结论,又如何呢?《没有银弹》一文认为"软件的特性本身导致了不大可能有任何的银弹"。Tuski 在 IFIP 大会上发表了一篇论文作为出色的回应,文中指出:
在所有被误导的科学探索中,最悲惨的莫过于对一种能够将一般金属变成金子的物质,即点金石的研究。这个由统治者不断地投入金钱,被一代代的研究者不懈追求的、炼金术中至高无上的法宝,是一种从理想化想象和普遍假设中——以为事情会像我们所认为的那样——提取出的精华。它是人类纯粹信仰的体现,人们花费了大量的时间和精力来认可和接受这个无法解决的问题。即使被证明是不存在,那种寻找出路和希望能一劳永逸的愿望,依然十分的强烈。而我们中的绝大多数总是很同情这些明知不可为而为之的人,因此它们总是得以延续。所以,将圆形变方的论文被发表,恢复脱发的洗液被研制和出售,提高软件生产率的方法被提出并成功地推销。
我们太过倾向于遵循我们自己的乐观主义(或者是发掘我们出资人的乐观主义)。我们太喜欢忽视真理的声音,而去听从万灵药贩卖者的诱惑。
我和 Turski 都坚持认为这个白日梦限制了向前的发展,浪费了精力。
"消极"主题。Harel 认识到《没有银弹》中的消极来自三个主题:
- 根本和次要问题的清晰划分
- 独立地评价每个候选银弹
- 仅仅预言了十年,而不是足够长的时间"出现任何重大的进步。"
第一个主题,它是整篇文章的主要观点。我仍然认为上述划分对于理解为什么软件难以开发是绝对关键的。对于应该做出哪些方面的改进,它也是十分明确的指南。
至于独立地考虑不同的候选银弹,《没有银弹》并非如此。各种各样的技术一个接一个地被提出,每一种都过分宣扬自身的效果。因此,依次独立的评估它们是非常公平的。我持反对态度的并不是这些技术,而是那种它们能起到魔术般作用的观点。Glass、Vessey 和 Conger 在他们 1992 年的论文中提供了充足的证据,指出对银弹的无谓研究仍未结束。
关于选择 10 年还是 40 年作为预言的期限,选择较短的时间是承认我们并没有足够强的能力可以预见到十年以后的事情。我们中间有谁可以在 1975 年预见到 80 年代的微型计算机革命吗?
对于十年的期限,还有其他的一些原因:各种银弹都宣称它们能够立刻取得效果。我回顾了一下,发现没有任何一种银弹声称"向我的秘方投资,在十年后你将获得成功"。另外,硬件的性能/价格比可能每十年就会有成百倍的增长,尽管这种比较不很合适,但是直觉上的确如此。我们确信会在下一个 40 年中取得稳步的发展。不过,以 40 年代价取得数量级的进展,很难被认为是不可思议的进步。
想象的试验。Harel 建议了一种想象的试验,他假设《没有银弹》是发表在 1952 年而不是 1986 年,不过表达的论断相同。他使用反证法来证明将根本和次要问题分开是不恰当的。
这种观点站不住脚。首先,《没有银弹》一开始就声称,50 年代的程序开发中曾占支配地位的次要困难,如今已经不存在了,并且消除这些困难已经产生了提高若干数量级的效果。
将辩论推回到 40 年前是不合理的,在 1952 年,甚至很难想象开发的次要问题不会占据开发工作的主要部分。
其次,Harel 所设想 50 年代行业所处状态是不准确的:
当时已经不是构建大型复杂系统的时代,程序员的工作模式已经成为常规个人程序的开发(在现代的编程语言中,大概是 100 ~ 200 行代码)。在已有技术和方法学的前提下,这些任务是令人恐怖的,处处都是错误、故障和落后的完成期限。
接着,他阐述了在传统的小型个人程序中,那些假设的错误、故障和落后的最终期限如何在接下来的 25 年中,得到数量级的改进和提高。
但是,50 年代该领域的实际情况并不是小型个人程序。在 1952 年,Univac 还在使用大约 8 人开发的复杂程序处理 1950 年的人口普查。其他机器则用于化学动力学、中子漫射计算、导弹性能计算等等。汇编语言、重定位的链接和装载程序、浮点解释系统等,还经常被使用。1955 年,人们开发 50 ~ 100 人年的商用程序。1956 年,通用电气在路易斯维尔的设备车间使用着超过 80,000 指令的薪资系统。1957 年,SAGE ANFSQ/7 防空计算机系统已经运转了两年,这个系统分布在 30 个不同的地点,是基于通讯、自消除故障的热备实时系统。因此,几乎无法坚持说个人程序的技术革命,能够用来描述 1952 年以来的软件工程上的努力。
银弹就在这里。Harel 接着提出了他自己的银弹,一种称为"香草(Vanilla)框架"的建模技术。文中并没有对方法提供足够评估的详细描述,不过给出了一些论文和参考资料。建模所针对的确实是软件开发的根本困难,即概念性要素的设计和调试,因此 Vanilla 框架有可能是革命性的。我也希望如此。Ken Brooks 在报告中提到,在实际工作中应用时,它的确是一种颇有帮助的方法学。
不可见性。Harel 强烈地主张软件的概念性要素本质上是拓扑的,这些关系可以用空间/图形方式来自然地表达:
适当使用可视化图形可以给工程师和程序员带来可观的成效。而且,这种效果并不仅仅局限于次要问题,开发人员思考和探索的质量也得到了改进。未来的成功系统的开发将围绕在可视化图形表达方式的周围。首先,我们会使用"合适的"实体和关系来形成概念,然后表达成一系列逐步完善的模型,不断地系统化阐明和精化设计概念。模型用若干可视化语言的适当组合来描述,它必须是多种语言的组合,因为系统模型具有若干方面的内容,每方面象变戏法般产生不同类型的思维图像。
..就使自己成为良好可视化表达方式而言,建模过程的某些方面并不会立刻出现改观。例如,变量和数据结构上的算法操作可能还是会采用文字性描述。
我和 Harel 颇为一致。我认为软件要素并不存在于三维空间中,因此并不存在概念性设计到图形简单两维或三维上的映射。他承认,我也同意——这需要多种图形,每种图形覆盖某个特定的方面,而且有些方面无法用图形来表达。
Harel 采用图形来辅助思考和设计的热情彻底地感染了我。我一直喜欢向准程序员提问,"下个十一月在哪?"如果觉得问题过于模糊,接着我会问,"告诉我,你自己关于时间历法的模型。"优秀程序员具有很强的空间想象能力,他们常常有时间的几何模型,而且无需考虑,就能理解第一个问题。他们往往拥有高度个性化的模型。
# Jone 的观点——质量带来生产率
Capers Jones 最开始在一系列备忘录里,而后在一本书里,提出了颇有洞察力的观点。很多和我有书信往来的人向我提到了他的观点,《没有银弹》如同当时的很多文章,关注于生产率——单位输入对应的软件产出。Jone 提出,"不。关注质量,生产率自然会随着提高。"他认为,很多代价高昂的后续项目投入了大量的时间和精力来寻找和修复规格说明中、设计和实现上的错误。他提供的数据显示了缺乏系统化质量控制和进度灾难之间的密切关系。我认同这些数据。不过,Boehm 指出,如果一味追求完美质量,生产率会像 IBM 的航天软件一样再次下降。
Coqui 也提出相似的主张:系统化软件开发方法的发展是为了解决质量问题(特别是避免大型的灾难),而不是出于生产率方面的考虑。
但是注意:70 年代,在软件生产上应用工程原理的目标是提高软件产品的质量、可测试性、稳定性以及可预见性——而不是软件产品的开发效率。
在软件生产上应用工程原理的驱动力是担心拥有无法控制的"艺术家们"而可能导致的巨大灾难,他们往往对异常复杂系统开发承担责任。
# 那么,生产率的情形如何?
生产率数据。生产率的数据非常难以定义、测量和寻找。Capers Jones 相信两个相隔十年、完全等同的 COBOL 程序,一个采用结构化方法开发,另一个不使用结构化方法,它们之间的差距是 3 倍。
Ed Yourdon 说,"由于工作站和软件工具,我看到了人们的工作获得了 5 倍的提高。"Tom DeMarco 认为"你的期望——十年内,由于所有的技术而使生产率得到数量级的提高——太乐观了。我没有看到任何机构取得数量级的进步。"
塑料薄膜包装的成品软件——购买,而非开发。我认为 1986 年《没有银弹》中的一个估计被证实是正确的:"我相信,这个大众市场是..软件工程领域意义最深远的开发方向。"从学科的角度说,不管和内部还是外部客户软件的开发相比,大众市场软件都几乎是一个崭新的领域。当软件包的销量一旦达到百万或者即使只是几千,这时关键的支配性问题就变成了质量、时机、产品性能和支撑成本,而不再是对于客户系统异常关键的开发成本。
创造性活动的强大工具。提高信息管理系统(MIS)编程人员生产率最戏剧化的方法是到一家计算机商店去,购买理应由他们开发的商业成品。这并不荒唐可笑。价格低廉、功能强大的薄膜包装软件已经能满足要求,而以前这会要求进行定制软件包的开发。比起复杂的大型产品工具,它们更加像电锯、电转和砂磨机。把它们组合成兼容互补的集合,像 Microsoft Works 和集成更好的 Claris Works 一样,能够带来巨大的灵活性。另外,象供人们使用的组合工具箱,其中的某些工具会经常被使用,以致于熟能生巧。这种工具必须注重常人使用的方便,而不是专业。
Ivan Selin,美国管理系统公司主席,在 1987 年曾写信给我:
我有些怀疑你的关于软件包没有真正地改变很多..的观点。我觉得你太过轻易地抛开了你的观察所蕴涵的事实;你观察到——[软件包]"可能比以前更加通用和更加容易定制一些,但并不太多。"即使在表面上接受了这种论述,我相信用户察觉到软件包更加通用和易于本地化,这种感觉使用户更容易接受软件包。在我公司发现的大多数情况中,是[最终用户],而不是软件人员,不愿意使用软件包,因为他们认为会失去必要的特性或功能。因此,对他们而言,易于定制是一个非常大的卖点。
我认为 Selin 是十分正确的——我低估了软件包客户化的程度和它的重要性。
# 面向对象编程——这颗铜质子弹可以吗?
本章一开始的描述提醒我们,当很多零件需要装配,而且每个零件可能很复杂时,如果它们的接口设计得很流畅,大量丰富的结构就能快速地组合在一起。
使用更大的零件来构建。面向对象编程的第一个特征是,它强制的模块化和清晰的接口。其次,它强调了封装,即外界无法看到组件的内部结构;它还强调了继承和层次化类结构以及虚函数。面向对象还强调了强抽象数据类型化,它确保某种特定的数据类型只能由它自身的相应函数来操作。
现在,无需使用整个 Smalltalk 或者 C++的软件包,就可以获得这些特点中的任意一个——其中一些甚至出现在面向对象技术之前。面向对象方法吸引人的地方类似于复合维他命药丸:一次性(即编程人员的培训)得到所有的好处。面向对象是一种非常有前途的概念。
面向对象技术为什么发展缓慢?《没有银弹》后的九年中,对面向对象技术的期望稳步增长。为什么增长如此缓慢?理论过多。James Coggins,已经在 The C++ Report 做了四年 "The best of comp.lang.c++"专栏的作者,他提出了这样的解释:
问题是 O-O 程序员经历了很多错综复杂混乱的应用,他们所关注的是低层次,而不是高层次的抽象。例如,他们开发了很多象链表或集合这样的类,而不是用户接口、射线束模型或者有限元素模型。不幸的是,C++中帮助程序员避免错误的强类型检查,使得从小型事物中构建大型物体非常困难。
他回归到基本的软件问题,主张一种解决软件不能满足要求的方法,即通过客户的参与和协作来提高脑力劳动的规模。他赞同自顶向下的设计:
如果我们设计大粒度的类,关注用户已经接触的概念,则在进行设计的时候,他们能够理解设计并提出问题,并且可以帮助设计测试用例。我的眼科客户并不关心堆栈,他们关心描述眼角膜形状的勒让德多项式。在这方面,小规模的封装带来的好处比较少。
David Parnas 的论文是面向对象概念的起源之一,他用不同的观点看这个问题。他写信给我:
答案很简单。因为[O-O]和各种复杂语言的联系已经很紧密。人们并没有被告诉 O-O 是一种设计的方法,并向他们讲授设计方法和原理,大家只是被告知 O-O 是一种特殊工具。而我们可以用任何工具写出优质或低劣的代码。除非我们给人们讲解如何设计,否则语言所起的作用非常小。结果是人们使用这种语言做出不好的设计,没有从中获得什么价值。而一旦获得的价值少,它就不会流行。
资金的先行投入,收益的后期获得。面向对象技术包含了很多方法学上的进步。面向对象技术的前期投入很多——主要是培训程序员用很新的方法思考,同时还要把函数打造成通用的类。我认为它的好处是客观实在的,并非仅仅是推测。面向对象应用在整个开发周期中,但是真正的获益只有在后续开发、扩展和维护活动中才能体现出来。Coggin 说:"面向对象技术不会加快首次或第二次的开发,产品族中第五个项目的开发才会异乎寻常的迅速。"
为了预期中的,但是有些不确定的收益,冒着风险投入金钱是投资人每天在做的事情。不过,在很多软件公司中,这需要真正的管理勇气,一种比技术竞争力或者优秀管理能力更少有的精神。我认为极度的前期投入和收益的推后是使 O-O 技术应用迟缓的最大原因。即使如此,在很多机构中,C++仍毫无疑问地取代了 C。
# 重用的情况怎样?
解决软件构建根本困难的最佳方法是不进行任何开发。软件包只是达到上述目标的方法之一,另外的方法是程序重用。实际上,类的容易重用和通过继承方便地定制是面向对象技术最吸引人的地方。
事情常常就是这样。当某人在新的做事方法上取得了一些经验,新模式就不再象一开始那么简单。
当然,程序员经常重用他们自己的手头工作。Jone 提到:
大多数有丰富经验的程序员拥有自己的私人开发库,可以使他们使用大约 30%的重用代码来开发软件。公司级别的重用能提供 70%的重用代码量,它需要特殊的开发库和管理支持。公司级别的重用代码也意味着需要对项目中的变更进行统计和度量,从而提高重用的可信程度。
W.Huang 建议用责任专家的矩阵管理来组织软件工厂,从而培养重用自身代码的日常工作习惯。
JPL 的 Van Snyder 向我指出,数学软件领域有着软件重用的长期传统:
我们推测重用的障碍不在生产者一边,而在消费者一边。如果一个软件工程师,潜在的标准化软件构件消费者,觉得寻找能满足他需要的构件,进行验证,比自行编写的代价更加昂贵时,重复的构件就会产生。注意我们上面提到的"觉得"。它和重新开发的真正投入无关。
数学软件上重用成功的原因有两个:(1)它很晦涩难懂,每行代码需要大量高智商的输入;(2)存在丰富的标准术语,也就是用数学来描述每个构件的功能。因此,重新开发数学软件构件的成本很高,而查找现有构件功能的成本很低。数学软件界存在一些长期的传统——例如,专业期刊和算法搜集,用适度成本提供算法,出于商业考虑开发的高质量算法(尽管成本有些高,但依旧适度)等——使查找和发现满足某人需要的构件比其他很多领域要容易。其他领域中,有时甚至不可能简洁地提出明确的要求。这些因素合在一起,使数学软件的重用比重新开发更有吸引力。
同样的原因,在很多其他领域中也可以发现相同的重用现象,如那些为核反应、天气模型、海洋模型开发软件的代码编制工作。这些领域都是在相同的课本和标准概念下逐步地发展起来的。
现在公司级别的重用情况如何?存在着大量的研究。美国国内的实践相对较少,有报道声称国外重用较多。
Jones 报告,在他公司的客户中,所有拥有 5000 名以上程序员的机构都进行正式的重用研究,而 500 名以下程序员的组织,只有不到 10%着手重用研究。报告指出,最具有重用潜质的企业中,重用性研究(而非部署)"是活跃和积极的,即使没有完全成功。"Ed Yourdon 报告,有一家马尼拉的软件公司,200 名程序员中有 50 名从事供其他人使用的重用模块的开发,"我所见到的个案非常少——是由于机构上因素而进行重用研究,而不是技术上的原因"。
DeMarco 告诉我,大众市场软件包提供了数据库系统等通用功能,充分地减轻了压力,减少了处在重用模块边缘的开发。 "不管怎样,重用的模块一般是一些通用功能。"
Parnas 写道:
重用是一件说起来容易,做起来难的事情。它同时需要良好的设计和文档。即使我们看到了并不十分常见的优秀设计,但如果没有好的文档,我们也不会看到能重用的构件。
Ken Brooks 关于预测产品通用化的一些困难的评论:"我不断地进行修改,即使在第五次使用我自己的个人用户界面库的时候。"
真正的重用似乎才刚刚开始。Jones 报告,在开放市场上仅有少量的重用代码模块,它们的价格在常规开发成本的 1%~ 20%。DeMacro 说:
对整个重用现象,我变得有些气馁。对于重用,现有理论几乎是整体缺乏。时间证明了使模块能够重用的成本非常高。
Yourdon 估计了这个高昂的费用:"一个良好的经验法则是可重用的构件的工作量是'一次性'构件的两倍。"在第一章的讨论中,我观察到了真正产品化构件所需的成本。因此,我对工作量比率的估计是三倍。
显然,我们正在看到很多重用的形式和变化,但离我们所期望的还远,还有很多需要学习的地方。
# 学习大量的词——对软件重用的一个可预见,但还没有被预言的问题
思索的层次越高,所需要处理的基本思考要素也就越多。因此,编程语言比机器语言更加复杂,而自然语言的复杂程度更高。高级语言有更广泛的词汇量、更复杂的语法以及更加丰富的语义。
作为一个科目,我们并没有就程序重用的实际情况,仔细考虑它蕴涵的意义。为了提高质量和生产率,我们需要通过经过调试的大型要素来构建系统,在编程语言中,这些函数的级别远远高于语句。所以,无论采用对象类库还是函数库的方式,我们必须面对我们编程词汇规模彻底扩大的事实。对于重用,词汇学习并不是思维障碍中的一小部分。
现在人们拥有成员超过 3000 个的类库。很多对象需要 10 到 20 个参数和可选变量的说明。如果想获得所有潜在的重用,任何使用类库编程的人员必须学习其成员的语法(外部接口)和语义(详细的功能行为)。
这项工作并不是没有希望的。一般人日常使用的词汇超过 10,000 个,受过教育的人远多于这个数目。另外,我们在自然而然地学习着语法和非常微妙的语义。我们可以正确地区分巨大、大、辽阔、大量和庞大。人们不会说:庞大的沙漠或者辽阔的大象。
对软件重用问题,我们需要研究适当的学问,了解人们如何拥有语言。一些经验教训是显而易见的:
- 人们在上下文中学习,所以我们需要出版一些复合产品的例子,而不仅仅是零部件的库。
- 人们只会记忆背诵单词。语法和语义是在上下文中,通过使用逐渐地学习。
- 人们根据语义上的分类对词汇组合规则进行分组,而不是通过比较对象子集。
# 子弹的本质——形势没有发生改变
现在,我们回到基本问题。复杂性是我们这个行业的属性,而且复杂性是我们主要的限制。R.L.Glass 在 1988 年的文字精确地总结了我在 1995 年的看法:
又怎么样呢?Parnas 和 Brooks 不是已经告诉我们了吗?软件开发是一件棘手的事情,前方并不会有魔术般的解决方案。现在是从业者研究和分析革命性进展的时刻,而不是等待或希望它的出现。
软件领域中的一些人发现这是一幅使人泄气的图画。他们是那些依然认为突破近在眼前的人们。
但是我们中的一些——那些非常固执,以致于可以认为是现实主义者的人——把它看成是清新的空气。我们终于可以将焦点集中在更加可行的事情上,而不是空中的馅饼。现在,有可能,我们可以在软件生产率上取得逐步的进展,而不是等待不大可能到来的突破。