四十年软件工程故事
潘加宇
本文刊登于《程序员》2008年9期。加上了被删除的参考文献部分。
2008年5月14-16日,在德国迷人的小镇Garmisch,举办了软件工程四十年纪念会议,Peter Naur、Brian Randell、M. Douglas McIlroy、Albert Endres、Luigi Dadda等40年前软件工程会议的关键人物重聚旧地。40年前的1968年,正是在此地举行的NATO(北约)科技委员会会议上,“软件工程”作为正式的术语被确定下来,标志着一个新学科的开始。Peter Naur和Brian Randell主编的会议报告中这样写道:“我们特意选择‘软件工程’这个颇具争议性的词,是为了暗示这样一种意见:软件的生产有必要建立在某些理论基础和实践指导之上——在工程学的某些成效卓著的分支中,这些理论基础和实践指导早已成为了一种传统。”
图1 1968年软件工程大会会场
软件工程这个学科还很年轻,Peter Naur和Brian Randell今天依然健在。作为著名的编程语言归约BNF范式中的N,Peter Naur因设计和定义了ALGOL 60而在2005年获得图灵奖。因IBM System360的工作于1999年获得图灵奖的Fred Brooks在《人月神话》的结尾比较了化学工程和软件工程。他认为:软件系统可能是人类所创造的最错综复杂的事物,软件工程还很年轻,需要继续探索和尝试。
这四十年的过程就是探索和尝试的过程,让我们来细细品味其中的科学精神之美。
软件工程的定义有很多版本,比较权威的是IEEE给出的定义:(1)将系统化的、规范的、可量化的方法应用于软件的开发、运行和维护,即,将工程应用于软件。(2)在(1)中所述方法的研究。
“(1) The application of a systematic, disciplined, quantifiable approach to the development, operation, and maintenance of software; that is, the application of engineering to software.
(2) The study of approaches as in (1).”
所以,软件工程远没有想象中那么高大神秘,它研究的就是我们日常开发软件的工作方式。“程序员”这三个字本就属于软件工程的范围。
关于软件工程和计算机科学的区别,Fred Brooks说:A scientist builds in order to learn; an engineer learns in order to build。更详细的可以看看David Parnas的“Software Engineering Programs Are Not Computer Science Programs”和Steve McConnell的所著“Professional Software Development”的第4章。或者对照一下图灵奖获得者:软件工程领域的David Parnas、Frederick P. Brooks和计算机科学领域的Donald E. Knuth、《程序员》上期介绍的YAO。
软件是为人开发的,软件是由人开发的。正是因为人的心理难以捉摸,人的大脑处理复杂性时速度和容量的局限。我们才需要过程来规范人的行为,需要方法来帮助人脑面对复杂性,需要工具来贯彻这些过程和方法。所以,软件工程的知识体系分为以下几层。我们按照这个金字塔结构,逐层回顾四十年来的历史。
图2 软件工程知识体系层次
一开始,软件团队是没有过程的,甚至没有团队的概念。没有需求规格说明,没有设计,程序员在大脑中直接将代码思考出来,拼凑到一起,交给客户使用。客户如果有要求,再来修改代码,如此反复。这种“编码-修改”做法对于很小的程序可以应付,当程序规模变得复杂时,付出的代价就很大了。
瀑布
“软件工程”概念的提出,促进了需求、分析、设计、实现、维护等软件生命周期概念的成熟。瀑布模型是最早的软件过程模型,从名字“瀑布”可以看出,通常人们认为瀑布模型中的各个步骤是一条线完成的。实际上在Winston W. Royce1970年的经典论文“Managing the Development of Large Software Systems”中有反馈的过程(见图3),作者本人也并不提倡以顺序模型作为团队的过程模型,另外,Royce并没有在论文中把他的过程模型叫做“瀑布”,只是后来其他人这么叫了。很多团队使用时是按照线性的方式使用的,这是一种误解。
图3 软件开发的瀑布模型(来自原文的图)
这里要提一下,瀑布模型的提出者Winston W. Royce(已于1995年去世)有时被简写为W. Royce,所以经常会引起误会,把他当成Walker Royce,后者是软件项目管理专家,曾任Rational软件公司副总裁,著有“Software Project Management: A Unified Framework”一书。
增量和迭代
使用瀑布模型,可以运行的产品很迟才能看到,这就潜伏了巨大的风险:很可能,集成之日也就是爆炸之日。为了提早获得可以运行的版本,可以先实现一些功能,再实现一些功能…每个增量交付一个可以运行的版本。
增量开发显著降低了风险,而且还因可运行产品的出现大大提升了士气。最有名的实践应该是Microsoft在1989年就开始使用的Daily Build(每日构建),被称为项目的“心跳”。当然,增量开发不一定意味着每日构建,如Fred Brooks所述[2],Bell Northern Research是“每周构建”。
增量经常和迭代连在一起说,不过两者是有区别的。增量是逐块建造的概念,迭代是反复求精的概念。二者不一定要绑在一起使用,但很明显,结合这两种方式是一种有效的做法。现在很多过程所说的迭代开发,默认的意思就是增量&迭代。Jeff Patton最近用两幅图表达了增量和迭代(http://www.agileproductdesign.com/blog/dont_know_what_i_want.html)。
图4 增量和迭代
统一过程
1987年,Ivar Jacobson离开Ericsson,成立了Objective Systems公司。他吸纳了增量迭代的思想,开发出Objectory过程,并且把过程当软件卖,价格卖到$25,000一份,以至于Ivar Jacobson不想在Addison-Wesley等出版社出书公开他的方法,因为卖一本书才得到3美元。1991年,Ericsson收购了该公司,并更名为Objectory AB(北欧出大师,所以我们常在软件开发的书籍和文章中看到××AB等文字,AB是瑞典语Altiebolag的缩写,意思是“公司”),Ivar Jacobson又回到了Ericsson。
1995年,Rational从Ericsson收购了Objectory,Ivar Jacobson开始和Grady Booch、James Rumbaugh一起开发UML。Philippe Kruchten则负责把Objectory过程和Rational公司多年的积累Rational Approach融合在一起,开发出了"Rational Unified Process" (RUP)以及4+1视图模型。RUP的中心思想是:用例驱动、架构为中心、迭代和增量。虽然是一个商业产品,但详尽的内容和灵活的组织,使得RUP成为软件团队中流传最广的软件过程模型,也成为团队学习软件工程和实施过程改进的重要资料。
图5 Rational Unified Process
Ivar Jacobson在IBM收购后离开了Rational。2005年,他发布了Essential Unified Process(EssUP)将之描述为“超轻和超敏捷的”RUP,并且提出了过程定义(PD)和过程(P)的观点,他认为统一过程是一个过程定义(PD),不是过程(P),团队不能看着别人的P好,就想着拿来就用,必须要找到自己的点。2007年,Ivar Jacobson的新观点是“过程够了,实践吧(Enough of Processes: Let's Do Practices)”。
Doug Rosenberg和Kendall Scott的ICONIX过程借鉴了Ivar Jacobson和统一过程的思想,而且以其小巧易懂,受到不少开发人员的欢迎。
敏捷运动
敏捷运动在1990年代中期兴起,当时敏捷过程被称为“轻量”过程。2001年,Kent Beck、Alistair Cockburn、Ward Cunningham、Martin Fowler、Jim Highsmith、Ron Jeffries、Jon Kern、Robert C. Martin、Steve Mellor、Ken Schwaber等人聚集在犹他州的Snowbird,决定把“敏捷”作为新的过程家族的名称,并提出以下宣言:
个体和交互 胜过 过程和工具
可以工作的软件 胜过 面面俱到的文档
客户合作 胜过 合同谈判
响应变化 胜过 遵循计划
随后,敏捷联盟成立,这是一个致力于传播敏捷过程的非营利组织。敏捷联盟每年召开敏捷大会,今年已经是第6年。
关于敏捷过程,比较全面的介绍文章是Martin Fowler的“The New Methodology”。每隔一段时间,Fowler会随着形势的变化更新此文。该文2005年12月版本列出的各种流行敏捷过程包括:极限编程(XP)、Scrum、Crystal、上下文驱动测试(Context Driven Testing)、精益开发(Lean Development)、统一过程(Unified Process)。
极限编程(XP)是敏捷过程的代表。1996年,Kent Beck为了挽救Chrysler Comprehensive Compensation (C3)项目而创建了XP过程,虽然Chrysler最终取消了该项目,但是Ron Jeffries和Ward Cunningham等人参与到了XP的工作中。1999年,Kent Beck出版了“Extreme Programming Explained: Embrace Change”'一书。XP一代相当于程序员的宣言,受到了程序员的热烈欢迎。2004年,该书第2版[16]出版,Kent Beck说自己几乎完全重写了整本书,书中关于是程序员是宇宙中心的内容少了很多,更多的是谈程序员和编程工作必须处于业务环境中,他们需要成为正常商业世界中的一部分。
过程评估和CMM
从1968年开始,Watts S. Humphrey是IBM负责软件部门的副总裁。1986年,Watts S. Humphrey离开IBM后,加入了SEI(卡内基·梅隆大学软件工程研究所),开始开发CMM(Capability Maturity Model,能力成熟度模型)。CMM一开始的目的是为军方制定一个好用的评估承包商的标准,因为SEI本来就是军方资助的机构。
1989年,在“Managing the Software Process”一书中,Humphrey描述了CMM。CMM可以看作是一个软件过程的元模型,定义了软件组织达到一定能力成熟度所需的关键过程域(KPA)。
等级名 |
特征 |
关键过程域 (KPA) |
初始级 |
以个人主观认为合适的方式来开发 |
|
可重复级 |
不存在组织范围的过程,利用已存在的项目管理实践和经验来开发 |
· 需求管理 · 软件项目规划 · 软件项目跟踪和监督 · 软件转包管理 · 软件质量控制 · 软件配置管理 |
已定义级 |
有定义好的属于组织范围的过程,按照过程有效的进行开发 |
· 组织过程焦点 · 组织过程定义 · 培训方案 · 集成软件管理 · 软件生产工程 · 组间协调 · 同行评审 |
已管理级 |
可以对过程能力进行量化,根据量化来预测和控制一个项目的过程绩效 |
· 软件质量管理 · 定量过程管理 |
优化级 |
过程能力可控、可改进,并且可以以量化方式来评估改进 |
· 过程变更管理 · 技术变更管理 · 故障预防 |
图6 CMM等级和KPA
1990年代中期,CMM开始在世界范围内流传开来,成为一些政府采纳的评估软件组织的标准,政府甚至对通过评估的软件组织加以资助。在这种激励下,想获得政府订单或者政府资助的软件组织纷纷力争通过CMM评估。目前,通过CMM/CMMI评估的组织数量前三位国家是:美国、印度和中国。
在1960年代,程序员随意地编写代码。虽然当时已经出现了FORTRAN等高级语言,但程序员把代码写在一起,代码中使用GOTO语句来跳转,使得程序的内部结构象“意大利面”,整个程序又象一块铁板,无法单独抽取其中一部分复用。
功能分解
1968年,Edsger W. Dijkstra发表"Go To Statement Considered Harmful",认为GOTO语句是有害的,应该把程序划分成多个子单元,每个子单元只做一件事,当重复的语句集合出现时,只需要调用相应子单元(函数)。这相当于封装和复用了共同的行为。
图7 功能分解:现实映射到函数
数据流
当软件的规模不断变大,大到不能一下子映射到代码级别时,就需要更大颗粒的分析设计方法。1970年代,数据流法出现了,有三种流行的流派:DeMarco方法(1978)、Gane/Sarsen方法(1979)以及Yourdon/Constantine方法(1979)。
数据流法把系统看作数据的加工机,数据流进去,经过加工,变成新的数据流出来。从最顶层开始(因为此时系统看是一个整体,所以表达的就是功能需求),一层一层向下求精,一直求精到泡泡所代表的加工成为可以编码的动作。
图8 数据流图,现实映射到数据流和加工
数据流法确实是能够严谨地把大问题分解为小问题的方法,它也可以扩展到企业建模(把企业看作是数据的加工机)。但这种方法从来没有象面向对象分析设计方法一样,出现UML这样的统一表示法,带动大量工具和书籍的产生。
在这个时期,Larry Constantine开始致力于研究软件设计的基本原则,他的许多著名观点(如耦合和内聚)成为结构化分析设计的指导原则,并被面向对象分析设计继承和发展,虽然Constantine没有在面向对象的旗号下做任何事情。
实体/关系
1970年代末,关系数据库开始变得流行。Peter Chen(陈品山)在1976提出实体关系(ER)模型,用实体和关系映射现实中的事物和概念。该模型提供了数据的图形视角,并能轻松转换为关系数据库模型。分析员很快认识到,ER模型可以用来表达大型软件的数据库设计,更宏观地把握业务,而且还有助于分析员和用户交流。
图9 实体-关系图,现实映射到实体和关系
数据流法结合实体关系法,曾经是比较流行的开发软件的方法。这种做法的一个问题是数据和行为是分离的,行为可以随意读写数据。另一个问题是分析和设计之间表达不一致,使得从设计回溯到分析相当困难。这正是面向对象分析设计所要改进的。
面向对象
Alan Kay说“面向对象”这个词是他在1967年首先使用的(http://www.purl.org/stefan_ram/pub/doc_kay_oop_en),但人们普遍认为,1967年由挪威的Ole-Johan Dahl和Kristen Nygaard设计的Simula-67是第一门面向对象语言,它是作为ALGOL的一个超集出现的。虽然Simula没有后继版本,但这个语言对后来的许多面向对象语言的设计者产生了很大的影响,
80年代初,Alan Kay在Palo Alto研发的Smalltalk语言被广泛使用(Kent Beck就是Smalltalk的拥护者),掀起了一场“面向对象运动”,许多面向对象语言随之诞生。Grady Booch在他的最新著作“Object-Oriented Analysis and Design with Applications”第3版中归纳如图10:
图10 有影响力的计算机语言谱系
面向对象的思想就是:假设系统由“对象”这样一种东西构成,对象封装了结构和行为。这种思考方式和人类的认知相当贴近,更有利于人脑去把握问题的复杂性。分类是人类认知的一种基本技能,分类哲学的讨论可以追溯到柏拉图的《政治家》和亚里士多德的《范畴》。
结构化分析设计和面向对象编程之间不能很好地过渡,到1980年代后期,不同的方法学家开始提出自己的面向对象分析设计方法学。这些方法学主要有:Booch、Shlaer/Mellor、Wirfs-Brock责任驱动设计、Coad/Yourdon、Rumbaugh OMT、Jacobson OOSE。
UML
这种百花齐放的局面带来了一个问题:各方法学有自己的一套概念、定义、标记符号和术语,但总的来说大同小异。这些细微的差异通常会造成混乱,使开发人员无从选择,也妨碍了面向对象分析设计的推广。
Wirfs-Brock |
Responsibility(责任) |
Booch |
Operation(操作) |
Coad/Yourdon |
Service(服务) |
Stroustrup |
Function(函数) |
其他很多方法学 |
Method(方法) |
图11 同一个概念,不同方法学的表达
1994年,在Rational工作的Rumbaugh和Booch开始合并OMT和Booch方法。随后,Jacobson带着他的OOSE方法学也加入了Rational公司,一同参与这项工作。他们三个人被称为“三友”(three amigo)。这项工作造成了很大的冲击,因为在此之前,各种方法学的拥护者觉得没有必要放弃自己已经采用的表示法,而接受统一的表示法。
1996年,三友开始与James Odell、Peter Coad、David Harel等来自其他公司的方法学家合作,吸纳了他们的成果精华。1997年9月,所有建议被合并成一套建议书提交给OMG。1997年11月,UML被OMG全体成员一致通过,并采纳为标准。UML诞生时,Martin Fowler就作了如下预测:
你应该使用UML吗?一个字:是!旧的面向对象符号正在快速地消逝。它们还会残留在UML稳固前出版的书上面,但新的书、文章等等将会全部以UML作为符号。如果你正在使用旧的符号,你就应该在1998年间转换到UML。如果你正要开始使用建模符号,你就该直接学习UML。
时间过去10年了,事实正是如此。以UML为契机,掀起了一股普及软件工程的热潮,比起UML出现之前,软件工程的书籍出现了爆炸性的增长。制定UML标准的角色(OMG)、根据标准开发工具的角色(UML工具厂商)、使用UML工具开发软件的角色(开发人员)这三种角色的剥离,也导致建模工具的数量和种类出现了爆炸性的增长。
现在,UML已经被ISO吸纳为标准,UML1.4.2即ISO/IEC 19501,UML2.1.2即ISO/IEC 19505。
模式运动
1979年,Christopher Alexander[33]开始使用“模式”来描述建筑的构造方法。1987年,Kent Beck和Ward Cunningham 尝试把这种思路应用到软件开发中,并在OOPSLA大会上发表了自己的看法。一直到1994年10月,被称为四人帮(GoF)的Erich Gamma, Richard Helm, Ralph Johnson和John Vlissides所写的《设计模式》上市(此书是1995年的版权,看来国内外出版业差不多,我们可以在2007年12月买到2008年1月第1版的书),模式的概念才流行起来。此书到2007年为止共重印36次,被翻译成13种其他语言,而且有不计其数的兄弟书籍诞生出来,“言必称模式”成为一种时髦,可谓影响深远。
现在,除了最常提到的GoF的23种设计模式之外,不断有各种各样的模式提出来,包括分析模式、架构模式、过程模式、组织模式、实现模式、反模式…..。
很长一段时间内,软件开发工具指的就是代码工具,而且编辑、调试、编译是分离的。后来慢慢出现了IDE(集成开发环境),各大工具厂商更是在IDE市场激战。这方面的故事,大家可以看李维的《Borland传奇》。
在软件工程工具如分析设计、过程管理等工具方面,却是一片空白。一直到1982年,Nastec公司开发出了DesignAid,该工具提供绘制系统设计图和建立数据字典的功能。到了1990年代,随着方法学繁荣和图形界面的普及,才出现了大量的设计工具,典型的代表是Rational Rose和Popkin System Architect。
最初的设计工具以独立的产品存在,而且只是提供了画图的功能,然后慢慢有了代码正向逆向工程。开发人员在设计工具里建好模型,再通过一个转换器在代码环境生成代码。设计工具的一个变种是成为代码环境的插件(Rational XDE,Together for VS.net等),直接在代码环境中创建设计模型,和代码高效同步。
接下来的趋势是设计工具和生命周期其他工具集成。2002年10月,Borland收购了当时UML工具厂商中的老二Togethersoft,这成为了导火索。之后,IBM、Telelogic、Borland等大厂商通过并购和放弃,打造出了新的品类――应用生命周期管理(ALM)工具。微软的工具Visual Studio Team System也在朝ALM工具方向进化。下表列出了三家ALM厂商一些产品的对比。
|
IBM Rational |
Telelogic |
Borland |
建模 |
Rational Software Architect Rational Rose |
System Architect Rhapsody Tau |
Together |
需求管理 |
RequisitePro |
DOORS |
CaliberRM |
配置管理 |
ClearCase |
Synengy |
StarTeam |
测试 |
Robot |
Logiscope |
SilkTest |
… |
… |
… |
… |
图12 各ALM工具厂商产品对照
现在,Rational和Telelogic都已经被IBM收入旗下,但Sparx Systems、NoMagic、Gentleware等中小厂商纷纷加入到这个市场中,竞争依然激烈。
1999年,我创建了UMLChina,从那时开始关注软件工程各方面的进展。到现在为止,我已经上门为超过100个软件开发团队提供需求和设计技能(根据我们上面的分类,这属于“方法”层面)服务。我发现一个有趣的现象,在开始服务之前的商议过程中,很多开发团队(不是每个团队)或多或少都会有人(不是每个人)或明或暗地表达出这样的观点:自己团队的难处与众不同,奇特的困难降临在他们身上,偏偏别人得以幸免。
尽管UMLChina一直强调自己的服务是“聚焦最后一公里”,坚信每一个开发团队都会在细节上和其他团队有所不同,而且也应该有所不同。但很多时候,我还是感觉到,开发团队还是高估了自己的“个性”,低估了“共性”。
最核心的共性问题,仍然是质量――能最大化获取利润的质量。它无非是两条路:增加收入――如何把东西更好地“卖”出去(给客户,给领导…);减少成本――如何用可复用的要素(组件、过程…)降低制造的成本。这些正是软件工程的不同分支(需求工程、架构设计、过程改进…)要研究的。四十年来的研究成果,肯定会有一些适合您的团队。这些成果是先行者们从自己或别人的血泪中提炼出来的,我们没有必要再重复挥洒血泪了。
[1] Naur, Peter, and Brian Randell, (eds.), Software Engineering: A Report on a Conference Sponsored by the NATO Science Committee, NATO, 1969. 原文可在Brian Randell的个人页面下载:http://homepages.cs.ncl.ac.uk/brian.randell/NATO/nato1968.PDF。本文中所引用句子参考了熊节的翻译
[2] Brooks, F. 著,UMLChina翻译组汪颖 译,《人月神话》20周年纪念版,清华大学出版社,2002年11月。
[3] IEEE Standards Collection: Software Engineering, IEEE Standard 610.12—1990, IEEE, 1993.
[4] Gibbs, N. E, Fairley, R. E. , Software Engineering Education: The Educational Needs of the Software Community. New York: Springer-Verlag, 1987.
[5]Parnas, D. ,Software Engineering Programs Are Not Computer Science Programs, IEEE Software, December 1999, 19-30.
[6] McConnell, S. 著,金戈 等译,《代码大全》第2版,电子工业出版社,2006年3月。
[7] Royce, W.W., Managing the Development of Large Software Systems Proc. IEEE WESCON, August 1970, pages 1-9. 网络下载:http://www.cs.umd.edu/class/spring2003/cmsc838p/Process/waterfall.pdf
[8] Royce, W, 软件项目管理-统一性框架(影印版),高等教育出版社,2003年1月。
[9] Cusumano, M. A., Selby, R. W.著,《微软的秘密》,北京大学出版社,1996年12月。.
[10] http://www.agileproductdesign.com/blog/dont_know_what_i_want.html
[11]Adriano Comai, Interview with Ivar Jacobson, http://www.analisi-disegno.com/uml/JacobsonInterview.html, September 1999
[12] http://www.jot.fm/issues/issue_2007_07/column5/
[13] http://www.iconixsw.com/
[14] http://martinfowler.com/articles/newMethodology.html
[15] Beck, K. 著,唐东铭 译,《解析极限编程:拥抱变化》,人民邮电出版社,2002
[16] Beck, K. 著,雷剑文,陈振冲,李明树 译,《解析极限编程:拥抱变化》(第2版),电子工业出版社,2006
[17] http://www.umlchina.com/Chat/kentbeck2005.htm, 2005年Kent Beck在UMLChina讲座录音。
[18] Humphrey, W. , Managing the Software Process, Addison-Wesley, 1989
[19]Dijkstra, E. , Go To Statement Considered Harmful. Communications of the ACM 11 (3): 147–148. March 1968.
[20] DeMarco, T. , Structured Analysis and System Specification, Yourdon Press, 1978
[21] Gane, G. , Sarsen, T. , Structured Systems Analysis: Tools and Techniques, Prentice Hall, 1979
[22] Yourdon, E. , Constantine, L. L. , Structured Design: Fundamentals of a Discipline of Computer Program and Systems Design, Prentice Hall, 1979
[23] Constantine, L. L., Control of Sequence and Parallelism in Modular Programs," AFIPS Conference Proceedings, 32: 409ff, Spring 1968
[24] Chen P. P. , The Entity Relationship Model - Toward A Unified View of Data, ACM Transactions on Database Systems 1(1): 9-36, 1976
[25] http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en
[26] Booch, G. ,Object-Oriented Analysis and Design with Applications (Third Edition), Addison-Wesley, 2005
[27] Shlaer, S. , Mellor, S. J. , Object-Oriented Systems Analysis: Modeling the World in Data, Yourdon Press, 1988
[28]Rebecca Wirfs-Brock, R., Wilkerson, B., Wiener, L. 著,张金明、陈少卿、谢武钦 译,《面向对象软件设计经典》,电子工业出版社,2003
[29] Peter Coad, P. , Yourdon E. 著,邵维忠、廖钢城、李力 译,《面向对象的分析》,北京大学出版社,1997。
[30] Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F., Lorensen, W., Object-Oriented Modeling and Design, Prentice Hall, 1991
[31] Jacobson, J., Christerson, M., Jonsson, P., Övergaard, G., Object-Oriented Software Engineering: A Use Case Driven Approach, Addison-Wesley, 1992.
[32] http://www.mmmbook.com/xprogrammer/XProgrammer5.pdf
[33]Alexander, C.著,赵冰 译,《建筑的永恒之道》,知识产权出版社,2002
[34] Gamma, E., Helm, R., Johnson, R., Vlissides, J.著,李英军 译,《设计模式:可复用面向对象软件的基础》,机械工业出版社,2000。
[35] 李维,《Borland传奇》(第2版),电子工业出版社,2004。