senline

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

四十年软件工程故事

潘加宇 

本文刊登于《程序员》2008年9期。加上了被删除的参考文献部分。

原文地址:四十年软件工程故事-潘加宇 (umlchina.com)

 

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在《人月神话》的结尾比较了化学工程和软件工程。他认为:软件系统可能是人类所创造的最错综复杂的事物,软件工程还很年轻,需要继续探索和尝试。

这四十年的过程就是探索和尝试的过程,让我们来细细品味其中的科学精神之美。

1、软件工程是什么

软件工程的定义有很多版本,比较权威的是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 ParnasFrederick P. Brooks和计算机科学领域的Donald E. Knuth、《程序员》上期介绍的YAO。

软件是为人开发的,软件是由人开发的。正是因为人的心理难以捉摸,人的大脑处理复杂性时速度和容量的局限。我们才需要过程来规范人的行为,需要方法来帮助人脑面对复杂性,需要工具来贯彻这些过程和方法。所以,软件工程的知识体系分为以下几层。我们按照这个金字塔结构,逐层回顾四十年来的历史。

 

图2 软件工程知识体系层次

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评估的组织数量前三位国家是:美国、印度和中国。

3、方法

在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种设计模式之外,不断有各种各样的模式提出来,包括分析模式、架构模式、过程模式、组织模式、实现模式、反模式…..。

4、工具

很长一段时间内,软件开发工具指的就是代码工具,而且编辑、调试、编译是分离的。后来慢慢出现了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。

 

posted on 2022-09-09 12:03  森蓝2010  阅读(277)  评论(0编辑  收藏  举报