UML用户指南(第2版.修订版)

978-7-115-29644-3
作者: 【美】Grady Booch James Rumbaugh Ivar Jacobson
译者: 邵维忠麻志毅马浩海刘辉
编辑: 杨海玲

图书目录:

详情

本书是UML方面的一部权威著作,三位作者是UML的创始人。书中为UML具体特征的使用提供了指南,描述了使用UML进行开发的过程,旨在让读者掌握UML的术语、规则和惯用法,以及如何有效地使用这种语言,知道如何应用UML去解决一些常见的建模问题。

图书摘要

软件开发方法学精选系列

Unified Modeling Language User Guide,Second Edition

UML用户指南(第2版·修订版)

[美]Grady Booch James Rumbaugh Ivar Jacobson 著

邵维忠 麻志毅 马浩海 刘辉 译

人民邮电出版社

北京

图书在版编目(CIP)数据

UML用户指南:第2版/(美)布奇(BOOCH,.)(美)兰宝(Rumbaugh,.),(美)雅各布(Jacobson,I.)著;邵维忠等译.--北京:人民邮电出版社,2013.1

(软件开发方法学精选系列)

书名原文:Unified Modeling Language User Guide,Second Edition

ISBN 978-7-115-29644-3

Ⅰ.①U… Ⅱ.①布…②兰…③雅…④邵… Ⅲ.①面向对象语言—程序设计 Ⅳ.①TP312

中国版本图书馆CIP数据核字(2012)第242102号

内容提要

本书是UML方面的一部权威著作,3位作者是面向对象方法最早的倡导者、UML的创始人。本版涵盖了UML2.0。书中为UML具体特征的使用提供了指南,描述了使用UML进行开发的过程,旨在让读者掌握UML的术语、规则和惯用法,以及如何有效地使用这种语言,知道如何应用UML去解决一些常见的建模问题。本书由7个部分共33章组成,每章都对一组UML特征及其具体用法进行了详细阐述,其中大部分按入门、术语和概念、常用建模技术、提示和技巧的方式组织。本书还为高级开发人员提供了在高级建模问题中应用UML的一条非常实用的线索。

本书适合作为高等院校计算机及相关专业本科生或研究生“统一建模语言(UML)”课程的教材,也适合从事软件开发的工程技术人员和软件工程领域的研究人员参考。

软件开发方法学精选系列

UML用户指南(第2版·修订版)

◆著 [美]Grady Booch James Rumbaugh Ivar Jacobson

译 邵维忠 麻志毅 马浩海 刘辉

责任编辑 杨海玲

◆人民邮电出版社出版发行  北京市崇文区夕照寺街14号

邮编 100061  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

北京鑫正大印刷有限公司印刷

◆开本:800×1000 1/16

印张:24.25

字数:535千字  2013年1月第1版

印数:1-3000册  2013年1月北京第1次印刷

著作权合同登记号 图字:01-2012-7097号

ISBN 978-7-115-29644-3

定价:59.00元

读者服务热线:(010)67132692 印装质量热线:(010)67129223

反盗版热线:(010)67171154

广告经营许可证:京崇工商广字第0021号

版权声明

Authorized translation from the English language edition,entitled The Unified Modeling Language User Guide,Second Edition,0321267974 by Grady Booch,James Rumbaugh,and Ivar Jacobson,published by Pearson Education,Inc.,publishing as Addison-Wesley,Copyright © 2005 Pearson Education,Inc.

All rights reserved.No part of this book may be reproduced or transmitted in any form or by any means,electronic or mechanical,including photocopying,recording or by any information storage retrieval system,without permission from Pearson Education,Inc.

CHINESE SIMPLIFIED language edition published by PEARSON EDUCATION ASIA LTD.and POSTS & TELECOM PRESS Copyright © 2013.

本书中文简体字版由Pearson Education Asia Ltd.授权人民邮电出版社独家出版。未经出版者书面许可,不得以任何方式复制或抄袭本书内容。

本书封面贴有Pearson Education(培生教育出版集团)激光防伪标签,无标签者不得销售。

版权所有,侵权必究。

译者序

开发一个复杂的软件系统和编写一个简单的程序大不一样。其间的差别,借用G.Booch 的比喻,如同建造一座大厦和搭建一个狗窝的差别。大型的、复杂的软件系统开发是一项系统工程,必须按工程学的方法来组织软件生产,需要经过一系列的软件生命周期阶段。这是人们从软件危机中获得的最重要的教益。这一认识促使了软件工程学的诞生。编程仍然是重要的,但是更具有决定意义的是系统建模。只有在分析和设计阶段建立了良好的系统模型,才有可能保证工程的正确实施。由于这一原因,在编程领域出现的许多新方法和新技术,总是很快地拓展到软件生命周期的分析与设计阶段。

面向对象方法正是经历了这样的发展过程,它首先在编程领域兴起,作为一种崭新的程序设计范型引起世人瞩目。继Smalltalk-80之后,20世纪80年代有一大批面向对象编程语言问世,标志着面向对象方法走向成熟和实用。此时,面向对象方法开始向系统设计阶段延伸,出现了一批早期的面向对象设计(OOD)方法。到80年代末期,面向对象方法的研究重点转向面向对象的分析(OOA),并将 OOA 与 OOD 密切地联系在一起,出现了一大批面向对象的分析与设计(OOA&D)方法。至1994年,公开发表并具有一定影响的OOA&D方法已达50余种。这种繁荣的局面表明面向对象方法已经深入到分析与设计领域。此后,大多数比较成熟的软件开发组织已经从分析、设计到编程、测试全面地采用面向对象方法,使面向对象无可置疑地成为软件领域的主流技术。

各种OOA&D方法都为面向对象理论与技术的发展做出了贡献。这些方法的主导思想以及所采用的主要概念与原则大体上是一致的,但是也存在不少差异。这些差异所带来的问题是:不利于OO方法的发展,妨碍了技术交流,也给用户的选择带来困惑。在这种形势下,统一建模语言(Unified Modeling Language,UML)应运而生。

UML是在多种面向对象分析与设计方法相互融合的基础上形成的,其发展历史可以大致概括为4个阶段。最初的阶段是面向对象方法学家的联合行动,由 G.Booch、J.Rumbaugh和I.Jacobson将他们各自的方法结合起来,形成了UML0.9。第二阶段是公司的联合行动,由十多家公司组成 UML 伙伴组织,共同提出了 UML1.0 和 1.1,于 1997年被对象管理组织(OMG)正式采纳作为建模语言规范。第三阶段是在OMG控制下对UML规范进行修订和改进,产生了 UML1.2、1.3、1.4和 1.5等版本。第四阶段是从 1999年开始酝酿,并于本世纪初实施的一次重大的修订,推出了UML2.0,继而进行了多次修订,产生了UML2.1到UML2.4一系列版本,提交到国际标准化组织ISO作为建模语言标准的提案,其中各个部分已陆续进入ISO的标准化日程。

UML 用于对软件密集型系统进行详述、可视化、构造和文档化,也可以用于业务建模以及其他非软件系统的建模。UML 定义了系统建模所需的概念并给出其可视化表示法,但是它并不涉及如何进行系统建模。因此它只是一种建模语言,而不是一种建模方法。UML 是独立于过程的,就是说,它可以适应不同的建模过程。UML 的出现使面向对象建模概念和表示法趋于统一和标准化。目前UML已成为被广泛公认的工业标准,拥有越来越多的用户。现今大部分面向对象系统的建模均采用UML。

G.Booch、J.Rumbaugh和I.Jacobson是UML的3位主要奠基人,被称为“三友”,他们为UML 的形成和发展做出了卓越贡献。在广大读者的殷切期待中,“三友”联名撰写的 3 本介绍UML以及Rational统一软件开发过程的著作(The Unified Modeling Language User Guide、The Unified Modeling Language Reference Manual和The Unified Software Development Process)于1999年由Addison-Wesley出版,深受广大读者的欢迎,被视为UML方面的权威性著作。在UML2.0问世之后,“三友”对他们的上述3本著作进行了再创作,以适应UML2.0的新内容,作为第2版,于2005年陆续出版。

现在我们翻译的《UML用户指南》第2版(The Unified Modeling Language User Guide,Second Edition)是“三友”上述3本著作中的一本,是阅读另外两本著作的基础。书中为如何使用UML提供了指南,旨在让读者掌握UML的术语、规则和惯用法,学会如何有效地使用UML进行开发,如何应用UML去解决常见的建模问题。实际上,这不仅仅是一部深入介绍UML的技术文献,而且处处闪烁着作者在方法学方面的真知灼见,凝结了作者在软件工程、面向对象方法、构件技术等诸多领域的经验和智慧。该书语言生动、深入浅出、实例丰富、图文并茂。对于想学习和使用 UML 的广大读者,这是一本难得的好书。该书的宗旨并不是全面地介绍 UML,也不是完整地介绍软件开发过程,这些内容属于“三友”的另外两本著作。

承担这样一本好书的翻译工作是1项愉快而又严肃的任务。尽管我们对UML进行过多年的研究,并且翻译过该书的第1版,但是在新版的翻译中仍不敢有驾轻就熟的心理。对翻译中遇到的一些疑难问题,往往要经过反复讨论,并通过对UML的进一步研究,才能获得比较准确的译法。忠实于原文是我们始终遵循的宗旨,但是原著中存在着个别前后不一致或者与UML规范不一致的现象,译文中采用了两种处理方式:对比较明显的错误在译文中做了订正,并通过译者注加以说明;对不太明显的错误按原文翻译,并在译者注中指出疑点。

本书的第一个译本于2006年6月由人民邮电出版社出版。承蒙广大读者的厚爱,先后9次印刷,累计印数达15000册。在此期间,UML2的版本升级并未影响本书的适用性,因为本书的宗旨并不是全面地介绍UML某个版本的具体细节,而是引导读者学习和使用 UML。人民邮电出版社为满足广大读者的迫切需求,决定再次出版这本书,趁此机会我们对2006年的译稿进行了全面的审核和修订。修订范围涉及全书各章,以及前言、术语表、附录和译者注,对一些翻译不太准确或前后不一致的地方逐一做了订正,对文字上不够通顺的地方也进行了修改。

书中的科技术语译法以国标GB/T11457《信息技术 软件工程术语》[1]和我国计算机界权威性工具书《计算机科学技术百科全书》[2]为基准。其中有几个比较关键的术语(例如 use case 和classifier 等),一些曾经流行的不同译法使读者对这些术语的含义产生了截然不同的理解。关于这些术语的译法问题,我们在《中国计算机学会通讯》2010年第1期上刊登的一篇短文曾对此专门加以论述,我们也将这篇短文附在本书最后,供读者参考。

本书的翻译和相关研究得到了高可信软件技术教育部重点实验室和北京大学信息科学技术学院的大力支持。北京大学软件研究所建模研究小组所开展的研究工作对本书的翻译提供了可靠的依据。在此,谨向上述单位和相关个人致以衷心感谢。同时,我们诚恳地希望广大读者对书中可能存在的疏漏和错误之处给予批评和指正。

译者

2012年10月于北京

[1].国家技术监督局.信息技术 软件工程术语 GB/T 11457——2006.北京:中国标准出版社,2006

[2].张效祥主编,计算机科学技术百科全书(第二版).北京:清华大学出版社,2005

译者简介

邵维忠 北京大学信息科学技术学院教授、博士生导师。1970年毕业于北京大学数学力学系,1979至1983年在计算机科学技术系任教并攻读硕士学位。早期主要从事操作系统和软件工程领域的研究。自1991年起注重面向对象建模方法的研究与教学,撰写和翻译了多部关于面向对象方法的学术著作。在软件工程环境、面向对象方法、建模语言、软件复用、构件技术和中间件技术等领域承担了多项国家高技术研究发展计划(863)项目、国家重大基础研究(973)项目和国家自然科学基金项目。曾获国家科技进步二等奖及多项国家部委级奖励。

麻志毅 博士,北京大学信息科学技术学院副教授,国家软件工程协会软件工程分会秘书长。主要研究领域为软件建模技术、模型驱动开发技术和软件工程支撑环境等。发表学术论文80余篇,出版著(译)作11部。曾获国家科技进步二等奖和国家科技攻关优秀成果奖等多项国家部委奖励。

马浩海 博士、教授、IBM资深软件工程师。2006年在北京大学信息学院获得计算机软件与理论专业理学博士学位。先后就职于内蒙古大学、Platform Computing和IBM Canada。已发表学术论文30余篇。主要研究领域为分布式计算和大规模数据处理、软件工程、面向对象技术、软件建模语言和模型驱动的软件开发技术。

刘辉 博士、副教授。2008年毕业于北京大学信息科学技术学院计算机软件与理论专业,获理学博士学位。同年进入北京理工大学计算机学院从事教学科研工作,入选校优秀青年教师资助计划。目前主要从事软件重构、软件演化、软件维护、软件测试等方面的研究和教学工作。现主持国家自然科学基金两项、教育部博士点基金一项、其他纵向科研项目4项。以第一作者在 IEEE Transactions on Software Engineering等期刊及ESEC\FSE、ASE等国际会议发表学术论文十余篇。

前言

统一建模语言(Unified Modeling Language,UML)是一种用于对软件密集型系统的制品进行可视化、详述、构造和文档化的图形语言。UML 给出了一种描绘系统蓝图的标准方法,其中既包括概念性的事物(如业务过程和系统功能),也包括具体的事物(如用特定的编程语言编写的类、数据库模式和可复用的软件构件)。

本书旨在教会读者如何有效地使用UML。

本书涵盖了UML 2.0[1]

目标

在本书中,读者将获益于以下几点。

明白UML是什么,不是什么,以及为什么UML对于开发软件密集型系统的过程非常重要。

掌握UML的术语、规则和惯用法,一般说来,还将学会如何有效地使用这种语言。

知道如何应用UML去解决许多常见的建模问题。

本书为UML具体特征的使用提供了参考资料,但它不是一本全面的UML参考手册。全面的参考请参阅我们编写的The Unified Modeling Language Reference Manual第2版(Rumbaugh、Jacobson、Booch合著,Addison-Wesley出版公司2005年出版)[2]

本书描述了使用UML进行开发的过程,但并没有提供对于开发过程的完整参考资料。开发过程是 The Unified Software Development Process(Jacobson、Booch、Rumbaugh 合著,Addison-Wesley出版公司1999年出版)[3]一书的重点。

最后,本书提供了如何运用UML去解决许多常见建模问题的提示和技巧,但没有讲述如何去建模。本书类似于一本编程语言的用户指南,它教用户如何使用语言,而不教用户如何编程。

读者对象

进行软件开发、部署和维护的人员均可使用 UML。本书主要针对用 UML 进行建模的开发组成员,但它也适用于为了理解、建造、测试和发布一个软件密集型系统而一起工作的人员,他们要阅读这些模型。虽然这几乎包含了软件开发组织中的所有角色,但本书特别适合下述人员阅读:分析员和最终客户(他们要详细说明系统应该具有的结构和行为)、体系结构设计人员(他们设计满足上述需求的系统)、开发人员(他们把体系结构转换为可执行的代码)、质量保证人员(他们检验并确认系统的结构和行为)、库管理人员(他们创建构件并对构件进行编目)、项目及程序管理者(他们一般是把握方向的领导者,要进行有序的管理,并合理地分配资源,以保证系统的成功交付)。

使用本书的人员应该具有面向对象概念的基本知识。如果读者具有面向对象编程的经验或懂得面向对象的方法,就能更容易掌握本书内容,但这并不是必需的。

怎样使用本书

初次接触UML的开发人员最好按顺序阅读本书。第2章提出了UML的概念模型,读者应特别予以注意。所有的章节都是这样组织的——每一章建立在前面各章的内容之上,循序渐进。

至于正在寻求用UML解决常见建模问题的有经验的开发人员,可以按任意顺序阅读本书。读者应该特别注意在各章中提到的常见建模问题。

本书的组织及特点

本书主要由7个部分组成:

第一部分 入门

第二部分 对基本结构建模

第三部分 对高级结构建模

第四部分 对基本行为建模

第五部分 对高级行为建模

第六部分 对体系结构建模

第七部分 结束语

本书还包含两个附录:UML表示法概要和 Rational统一过程概要。在附录后,提供了一个常见术语表和一个索引。

每章都描述了针对UML具体特征的用法,其中的大部分按下述4节的方式组织:

(1)入门;

(2)术语和概念;

(3)常用建模技术;

(4)提示和技巧。

第3节“常用建模技术”提出一组常见建模问题并予以解决。为了便于读者浏览本书找到这些UML的应用场合,每一个问题都标有一个明显的标题,如下例所示。

对体系结构模式建模

每一章都从它所涵盖的特征概要开始,如下例所示。

本章内容

主动对象、进程和线程

对多控制流建模

对进程间通信建模

建立线程安全的抽象

类似地,把附加的解释和一般性的指导分离出来作为注解,如下例所示。

注解 UML 中的抽象操作对应于 C++中的纯虚操作;叶子操作对应于 C++的非虚操作。

UML的语义是非常丰富的,因此对一个特征的描述自然会涉及另一个特征。在这种情况下,在自然段的最后部分标注交叉引用,正如本段这样。

【第25章讨论构件。】

在图中使用灰色字[4]是为了表明这些文字不是模型本身的一部分,只是用于解释模型。程序代码用Courier字体表示以示区别,如this example。

致谢

作者向Bruce Douglass、Per Krol和Joaquin Miller表示感谢,谢谢他们帮助审阅了第2版的书稿。

UML简史

通常公认的第一种面向对象语言是1967年由Dahl和Nygaard在挪威开发的Simula-67。虽然该语言从来没有得到大量拥护者,但是它的概念给后来的语言以很大启发。Smalltalk在20世纪80年代早期得到了广泛的使用,到20世纪80年代晚期跟着出现了其他的面向对象语言,如Objective C、C++和Eiffel等。方法学家面对新型面向对象编程语言的涌现和不断增长的应用系统复杂性,开始试验用不同的方法来进行分析和设计,由此在20世纪80年代出现了面向对象建模语言。在1989年到1994年之间,面向对象的方法从不足10种增加到50多种。面对这么多的方法,很多用户很难找到一种完全满足他们要求的建模语言,于是就加剧了所谓的“方法战”。一些杰出的方法脱颖而出,其中包括Booch方法、Jacobson的OOSE(面向对象的软件工程)和Rumbaugh 的 OMT(对象建模技术)。其他的重要方法还有 Fusion 方法、Shlaer-Mellor 方法和Coad-Yourdon方法。这些方法中的每一种方法都是完整的,但是每一种方法又都被认为各有优点和缺点。简单来说,Booch方法在项目的设计和构造阶段的表达力特别强,OOSE对以用况作为一种途径来驱动需求获取、分析和高层设计提供了极好的支持,而OMT对于分析和数据密集型信息系统最为有用。

到20世纪90年代中期,一个关键的想法开始形成。当时Grady Booch(Rational软件公司)、James Rumbaugh(通用电气公司)、Ivar Jacobson(Objectory公司)和其他一些人开始从彼此的方法中取长补短,他们的共同成果开始在全球范围内被公认为是领导性的面向对象方法。作为Booch方法、OOSE方法和OMT方法的主要作者,促使我们 3个人创建统一建模语言的原因有3个。第一,我们的方法已经在朝着相互独立的方向演化,而我们希望它朝着一个方向演化,这样可以消除任何不必要的和不合理的潜在差别,因为这样的差别会加重用户的疑惑。第二,通过统一我们的方法,能够给面向对象的市场带来一定的稳定,能够让人们使用一种成熟的建模语言去设计项目,使工具开发人员把焦点集中于最有用的特征。第三,希望我们的合作能够改进早期的3种方法,帮助我们吸取教训,解决以前的方法不能妥善处理的问题。

统一工作之始,我们确立了3个工作目标。

(1)运用面向对象技术对系统进行从概念到可执行制品的建模。

(2)解决复杂系统和关键任务系统中固有的规模问题。

(3)创造一种人和机器都可以使用的建模语言。

设计一种用于面向对象分析和设计的语言与设计一种编程语言不同。首先,必须缩小问题范围:这种语言是否应包含需求描述?这种语言是否应支持可视化编程?其次,必须在表达能力和表达的简洁性之间做好平衡。太简单的语言会限制能够解决问题的范围,而太复杂的语言会使开发人员无所适从。在统一现有方法的情况下,也必须小心从事。若对语言进行太多的改进,会给已有用户造成混乱;若不对语言进行改进,则会失去赢得更广大的用户群和使语言得到简化的时机。UML的定义力争在这些方面做出最好的选择。

1994年10月,Rumbaugh加入Booch所在的Rational公司,自此正式开始了UML的统一工作。我们的计划最初注重于联合Booch方法和OMT方法。“统一方法”(当时的名称)0.8版本(草案)在1995年10月发布。差不多就在那时,Jacobson也加入了Rational公司,于是UML项目的范围又做了扩充,把OOSE也结合进来。经过我们的努力,在1996年6月发布了UML 0.9版本。1996 年全年,我们都在软件工程界征求和收集反馈意见。在此期间,明显地有很多软件组织把UML作为商业战略来考虑。我们与几个愿意致力于定义一个强大而完善的UML的组织一起成立了一个UML伙伴组织。对UML 1.0版本做出贡献的合作伙伴有DEC、HP、I-Logix、Intellicorp、IBM、ICON Computing、MCI Systemhouse、Microsoft、Oracle、Rational、TI和Unisys。这些合作伙伴协作产生的UML 1.0版本是一个定义明确、富有表现力、强大、可应用于广泛问题域的建模语言。Mary Loomis帮助说服OMG(对象管理组织)发布了一个标准建模语言的提案需求(RFP)。在1997年1月,作为对该提案的响应,UML 1.0作为标准化的建模语言提交给OMG。

在1997年1月至7月之间,合作伙伴的队伍不断扩大,实际上包括了所有对最初OMG的提议做出贡献的公司,它们是 Andersen Consulting、Ericsson、ObjecTime Limited、Platinum Technology、PTech、Reich Technologies、Softeam、Sterling Software和Taskon。为了制定UML规范,并把 UML 与其他的标准化成果结合起来,成立了一支由 MCI Systemhouse 公司的 Cris Kobryn领导并由Rational公司的Ed Eykholt管理的语义任务组。在1997年7月,把UML的修改版(1.1版本)提交给OMG,申请进行标准化审查。1997年9月,OMG的分析与设计任务组(Analysis and Design Task Force,ADTF)和OMG的体系结构部接受了该版本,并把它提交给OMG的全体成员进行表决。1997年11月14日,UML 1.1版本被OMG采纳。

几年来,UML一直由OMG的修订任务组(Revision Task Force,RTF)维护,陆续研发了UML的1.3、1.4和1.5版本。从2000年到2003年,一个经过扩充了的新的伙伴组织制定了一个升级的UML规范,即UML 2.0。由IBM的Bran Selic领导的定案任务组(Finalization Task Force,FTF)对这个版本进行了为期一年的评审,UML 2.0的正式版本于2005年初被OMG采纳。UML 2.0是对UML 1的重大修订,包括了大量的新增特性。此外,基于先前版本的经验,UML 2.0对先前版本的构造物做了很多的修改。可以在OMG的网站上获得当前的UML规范文档。

UML 是很多人的工作成果,它的思想来自于大量的先前工作。重新构造一个贡献者的完整列表将是一项很大的历史性研究工程,根据对UML影响大小来识别那么多的先驱者就更为困难了。同所有的科学研究和工程实践一样,UML只是站在巨人肩上而已。

[1].UML2.0发布之后版本已多次更新,各个版本统称为UML2,目前最新的版本是UML2.4。本书绝大部分内容对UML2.0之后的各个版本仍然适应。——译者注

[2].中文版已由机械工业出版社出版,中文书名《UML参考手册》。——编者注

[3].中文版已由机械工业出版社出版,中文书名《统一软件开发过程》。——编者注

[4].本书中用灰色字代替原版中的蓝字表示这种区别。——编者注

第一部分 入门

第1章 为什么要建模

本章内容

建模的重要性

建模的4项原理

软件系统的基本蓝图

面向对象建模

成功的软件组织应该总是能够交付满足其用户需要的软件。如果一个软件组织能够及时并可预测地开发出这样的软件,并能够有效地利用人力和物力资源,那么这个软件组织就是可持续发展的。

在上段话里有一个重要的含义:一个开发队伍的主要产品不应该是一堆漂亮的文档、世界级的会议、伟大的口号或者几行获得普利策奖金的源代码,而应该是满足不断发展的用户及其业务需要的优秀软件。其他的一切事情都是次要的。

不幸的是,很多软件组织把“次要的”和“不重要的”的含义搞混了。为了得到满足预期功能的软件,必须到用户中去,以一种训练有素的方式访问用户,去揭示系统的真实需求。为了开发出具有持久质量的软件,必须打好能适应变化的、坚实的体系结构基础。为了能快速、有效地开发软件,尽量减少软件废品和重复工作,必须有合适的人员和合适的工具以及合适的工作重点。为了能一贯地、可预测地做到这些,并使得在整个系统的生命期内花费合理,必须有一个能适应业务和技术变化的合理的开发过程。

建模是开发优秀软件的所有活动中的核心部分,其目的是为了把想要得到的系统结构和行为沟通起来,为了对系统的体系结构进行可视化和控制,为了更好地理解正在构造的系统,并经常揭示简化和复用的机会,同时也是为了管理风险。

1.1 建模的重要性

如果想搭一个狗窝,备好木料、钉子和一些基本工具(如锤子、锯和卷尺)之后,就可以开始工作了。从制订一点初步计划到完成一个满足适当功能的狗窝,可能不用别人帮助,在几个小时内就能够实现。只要狗窝够大且不太漏水,狗就可以安居。如果未能达到希望的效果,返工总是可以的,无非是让狗受点委屈。

如果想为家庭建造一所房子,备好木料、钉子和一些基本工具之后,也能开始工作,但这将需要较长的时间,并且家庭对于房子的需求肯定比狗对于狗窝的需求要多。在这种情况下,除非曾经多次建造过房子,否则就需要事先制定出一些详细的计划,再开始动工,才能够成功。至少应该绘制一些表明房子是什么样子的简图。如果想建造一所能满足家庭的需要并符合当地建筑规范的合格房屋,就需要画一些建筑图,以便能想清楚房间的使用目的以及照明、取暖和水管装置的实际细节问题。做出这些计划后,就能对这项工作所需的时间和物料做出合理的估计。尽管自己也可能建造出这样的房屋,但若有其他人协作,并将工程中的许多关键部分转包出去或购买预制的材料,效率就会高得多。只要按计划行事,不超出时间和财务的预算,家庭多半会对这新房感到满意。如果不制定计划,新房就不会完全令人满意。因此,最好在早期就制定计划,并谨慎地处理好所发生的变化。

如果你要建造一座高层办公大厦,若还是先备好木料、钉子和一些基本工具就开始工作,那将是非常愚蠢的。因为你所使用的资金可能是别人的,他们会对建筑物的规模、形状和风格做出要求。同时,他们经常会改变想法,甚至是在工程已经开工之后。由于失败的代价太高了,因此必须要做详尽的计划。负责建筑物设计和施工的是一个庞大的组织机构,你只是其中的一部分。这个组织将需要各种各样的设计图和模型,以供各方相互沟通。只要得到了合适的人员和工具,并对把建筑概念转换为实际建筑的过程进行积极的管理,将会建成这座满足使用要求的大厦。如果想继续从事建筑工作,那么一定要在使用要求和实际的建筑技术之间做好平衡,并且处理好建筑团队成员们的休息问题,既不能把他们置于风险之中,也不能驱使他们过分辛苦地工作以至于精疲力尽。

奇怪的是,很多软件开发组织开始想建造一座大厦式的软件,而在动手处理时却好像他们正在仓促地造一个狗窝。

有时你是幸运的。如果在恰当的时间有足够的合适人员,并且其他一切事情都很如意,你的团队有可能(仅是可能)推出一个令用户眼花缭乱的软件产品。然而,一般的情况下,不可能所有人员都合适(合适的人员经常供不应求),时间并不总是恰当的(昨天总是更好),其他的事情也并不尽如人意(常常由不得自己)。现在对软件开发的要求正在日益增加,而开发团队却还是经常单纯地依靠他们唯一真正知道如何做好的一件事——编写程序代码。英雄式的编程工作成为这一行业的传奇,人们似乎经常认为更努力地工作是面对开发中出现的各种危机的正常反应。然而,这未必能产生正确的程序代码,而且一些项目是非常巨大的,无论怎样延长工作时间,也不足以完成所需的工作。

如果真正想建造一个相当于房子或大厦类的软件系统,问题可不是仅仅编写许多软件。事实上,关键是要编出正确的软件,并考虑如何少写软件。要生产合格的软件就要有一套关于体系结构、过程和工具的规范。即使如此,很多项目开始看起来像狗窝,但随后发展得像大厦,原因很简单,它们是自己成就的牺牲品。如果对体系结构、过程或工具的规范没有作任何考虑,总有一天狗窝会膨胀成大厦,并会由于其自身的重量而倒塌。狗窝的倒塌可能使你的狗恼怒;同理,不成功的大厦则将对大厦的租户造成严重的影响。

不成功的软件项目失败的原因各不相同,而所有成功的项目在很多方面都是相似的。成功的软件组织有很多成功的因素,其中共同的一点就是对建模的采用。

建模是一项经过检验并被广为接受的工程技术。建立房屋和大厦的建筑模型,能帮助用户得到实际建筑物的印象,甚至可以建立数学模型来分析大风或地震对建筑物造成的影响。

建模不只适用于建筑业。如果不首先构造模型(从计算机模型到物理风洞模型,再到与实物大小一样的原型),就装配新型的飞机或汽车,那简直是难以想象的。新型的电气设备(从微处理器到电话交换系统)需要一定程度的建模,以便更好地理解系统并与他人交流思想。在电影业,情节串联板是产品的核心,这也是建模的一种形式。在社会学、经济学和商业管理领域也需要建模,以证实人们的理论或用最小限度的风险和代价试验新的理论。

那么,模型是什么?简单地说:

模型是对现实的简化。

模型提供了系统的蓝图。模型既可以包括详细的计划,也可以包括从很高的层次考虑系统的总体计划。一个好的模型包括那些有广泛影响的主要元素,而忽略那些与给定的抽象水平不相关的次要元素。每个系统都可以从不同的方面用不同的模型来描述,因而每个模型都是一个在语义上闭合的系统抽象。模型可以是结构性的,强调系统的组织。它也可以是行为性的,强调系统的动态方面。

为什么要建模?一个基本理由是:

建模是为了能够更好地理解正在开发的系统。

通过建模,要达到以下4个目的。

(1)模型有助于按照实际情况或按照所需要的样式对系统进行可视化。

(2)模型能够规约系统的结构或行为。

(3)模型给出了指导构造系统的模板。

(4)模型对做出的决策进行文档化。

【第2章讨论UML如何完成这4件事情。】

建模并不只是针对大的系统。甚至像狗窝那样的软件也能从一些建模中受益。然而,可以明确地讲,系统越大、越复杂,建模的重要性就越大,一个很简单的原因是:

因为不能完整地理解一个复杂的系统,所以要对它建模。

人对复杂问题的理解能力是有限的。通过建模,缩小所研究问题的范围,一次只着重研究它的一个方面,这就是Edsger Dijkstra几年前讲的“分而治之”的基本方法,即把一个困难问题划分成一系列能够解决的小问题;解决了这些小问题也就解决了这个难题。此外,通过建模可以增强人的智力。一个适当选择的模型可以使建模人员在较高的抽象层次上工作。

任何情况下都应该建模的说法并没有落到实处。事实上,一些研究指出,大多数软件组织没有做正规的建模,即使做了也很少。按项目的复杂性划分一下建模的使用情况,将会发现:项目越简单,采用正规建模的就越少。

这里强调的是“正规”这个词。实际上,开发者甚至对非常简单的项目也要做一些建模工作,虽然很不正规。开发者可能在一块黑板上或一小片纸上勾画出他的想法,以对部分系统进行可视化表示,或者开发组可能使用CRC卡片描述一个场景或某种机制的设计。使用任何一种这样的模型都没有什么错。如果它能行得通,就可以使用。然而,这些非正规的模型经常是太随意了,它没有提供一种容易让他人理解的共同语言。建筑业、电机工程业和数学建模都有通用的建模语言,在软件开发中使用一种共同的建模语言进行软件建模同样能使开发组织获益匪浅。

每个项目都能从一些建模中受益。即使在一次性的软件开发中——由于可视化编程语言的支持,可以轻而易举地扔掉不适合的软件。建模也能帮助开发组更好地对系统计划进行可视化,并帮助他们正确地进行构造,使开发工作进展得更快。如果根本不去建模,项目越复杂,就越有可能失败或者构造出错误的东西。所有实用系统都有一个自然趋势:随着时间的推移变得越来越复杂。虽然今天可能认为不需要建模,但随着系统的演化,终将会对这个决定感到后悔,但那时为时已晚。

1.2 建模原理

各种工程学科都有其丰富的建模运用历史。这些经验形成了建模的四项基本原理,现分别叙述如下。

第一,选择要创建什么模型,对如何动手解决问题和如何形成解决方案有着意义深远的影响

换句话说,就是要好好地选择模型。正确的模型将清楚地表明最棘手的开发问题,提供不能轻易地从别处获得的洞察力;错误的模型将使人误入歧途,把精力花在不相关的问题上。

暂时先把软件问题放在一边,假设现在正试图解决量子物理学上的一个问题。诸如光子在时空中的相互作用问题,其中充满了令人惊奇的难解的数学问题。选择一个不同的模型,所有的复杂问题一下子就变得可行了(虽然不容易解决)。在这个领域中,这恰恰是费曼图的价值,它提供了对非常复杂问题的图形表示。类似地,在一个完全不同的领域里,假设正在建造一座新建筑,将会关心疾风对它的影响。如果建立了一个物理模型,并拿到风洞中去实验,虽然小模型没有精确地反映出大的实物,但也可以从中找出一些有趣的东西。因此,如果正在建立一个数学模型,然后去模拟,将知道一些不同的东西;与使用物理模型相比,也可能获得更多新的场景。通过对模型进行严格的持续的实验,将更信任已经建模的系统,事实上,它在现实世界中将像期望的那样工作得很好。

对于软件而言,所选择的模型将在很大程度上影响对领域的看法。如果以数据库开发者的观点建造一个系统,可能会注意实体——联系模型,该模型把行为放入触发器和存储过程中。如果以结构化开发者的观点建造一个系统,可能得到以算法为中心的模型,其中包含从处理到处理的数据流。如果以面向对象开发者的观点建造一个系统,将可能得到这样一个系统:它的体系结构以一组类和交互模式(指出这些类如何一起工作)为中心。可执行的模型对测试有很大帮助。上述的任何一种方法对于给定的应用系统和开发文化都可能是正确的,然而经验表明,在构建有弹性的体系结构中面向对象的方法表现得更为出众,即使对使用大型数据库或计算单元的系统也是如此。尽管如此,但要强调一点,不同的方法将导致不同种类的系统,并且代价和收益也是不同的。

第二,可以在不同的精度级别上表示每一种模型

如果正在建造一座大厦,有时需要从宏观上让投资者看到大厦的样子,感觉到大厦的总体效果。而有时又需要认真考虑细节问题,例如,对复杂棘手的管道的铺设,或对罕见的结构件的安装等。

对于软件模型也是如此。有时一个快速简洁且是可执行的用户界面模型正是所需要的,而有时必须耐着性子对付比特,例如,描述跨系统接口或解决网络瓶颈问题就是如此。在任何情况下,最好的模型应该是这样的:它可以让你根据谁在进行观察以及为什么要观察选择它的详细程度。分析人员或最终用户主要考虑“做什么”的问题,开发人员主要考虑“怎样做”的问题。这些人员都要在不同的时间以不同的详细程度对系统进行可视化。

第三,最好的模型是与现实相联系的

如果一个建筑物的物理模型不能反映真实的建筑物,则它的价值是很有限的;飞机的数学模型,如果只是假定了理想条件和完美制造,则可能掩盖真实飞机的一些潜在的、致命的现实特征。最好是拥有能够清晰地联系实际的模型,而当联系很薄弱时能够精确地知道这些模型如何与现实脱节。所有的模型都对现实进行了简化;诀窍是,确保这种简化不要掩盖掉任何重要的细节。

软件领域中结构化分析的致命弱点是在分析模型和系统设计模型之间没有基本的联系。随着时间的推移,这个不可填充的裂缝会使系统构思阶段和实施阶段出现不一致。在面向对象的系统中,可以把各个几乎独立的系统视图连结成一个完整的语义整体。

第四,单个模型或视图是不充分的。对每个重要的系统最好用一小组几乎独立的模型从多个视角去逼近

如果正在建造一所建筑物,会发现没有任何一套单项设计图能够描述该建筑的所有细节。至少需要楼层平面图、立面图、电气设计图、采暖设计图和管道设计图。并且,在任何种类的模型中都需要从多视角来把握系统的范围(例如不同楼层的蓝图)。

在这里的重要短语是“几乎独立的”。在这个语境中,它意味着各种模型能够被分别进行研究和构造,但它们仍然是相互联系的。如同建造建筑物一样,既能够单独地研究电气设计图,但也能看到它如何映射到楼层平面图中,以及它与管道设计图中的管子排布的相互影响。

面向对象的软件系统也如此。为了理解系统的体系结构,需要几个互补和连锁的视图:用况视图(揭示系统的需求)、设计视图(捕获问题空间和解空间里的词汇)、交互视图[1](展示系统各部分之间以及系统与环境之间的联系)、实现视图(描述系统的物理实现)和部署视图(着眼于系统的工程问题)。每一种视图都可能有结构方面和行为方面。这些视图一起从整体上描绘了软件蓝图。

【第2章讨论这5种视图。】

根据系统的性质,一些模型可能比另一些模型要重要。例如,对于数据密集型系统,表达静态设计视图的模型将占主导地位;对于图形用户界面密集型系统,静态和动态的用况视图就显得相当重要;在硬实时系统中,动态进程视图尤为重要;最后,在分布式系统中,例如 Web 密集型的应用,实现模型和部署模型是最重要的。

1.3 面向对象建模

土木工程师构造了很多种模型。通常这些模型能帮助人们可视化并说明系统的各部分以及这些部分之间的相互关系。根据业务或工程中所着重关心的内容(例如为了帮助研究一个结构在地震时的反应)工程师也可以建立动态模型。各种模型的组织是不同的,各有自己的侧重点。对于软件,有好几种建模的方法。最普通的两种方法是从算法的角度建模和从面向对象的角度建模。

传统的软件开发是从算法的角度进行建模。按照这种方法,所有的软件都用过程或函数作为其主要构造块。这种观点导致开发人员把精力集中于控制流程和对大的算法进行分解。这种观点除了常常产生脆弱的系统之外没有其他本质上的害处。当需求发生变化(总会变化的)以及系统增长(总会增长的)时,用这种方法建造的系统就会变得很难维护。

现代的软件开发采用面向对象的观点进行建模。按照这种方法,所有软件系统都用对象或类作为其主要构造块。简单地讲,对象通常是从问题空间或解空间的词汇中抽取出来的东西;类是对具有共同性质的一组对象(从建模者的视角)的描述。每一个对象都有标识(能够对它命名,以区别于其他对象)、状态(通常有一些数据与它相联系)和行为(能对该对象做某些事,它也能为其他对象做某些事)。

例如,可考虑把一个简单的计账系统的体系结构分成3层:用户界面层、业务服务层和数据库层。在用户界面层,将找出一些具体的对象,如按钮、菜单和对话框。在数据库层,将找出一些具体的对象,例如描述来自问题域实体的表,包括顾客、产品和订单等。在中间层,将找出诸如交易、业务规则等对象,以及顾客、产品和订单等问题实体的高层视图。

可以肯定地说,面向对象方法是软件开发方法的主流部分,其原因很简单,因为事实已经证明,它适合于在各种问题域中建造各种规模和复杂度的系统。此外,当前的大多数程序语言、操作系统和工具在一定程度上都是面向对象的,并给出更多按对象来观察世界的理由。面向对象的开发为使用构件技术(如J2EE或.NET)装配系统提供了概念基础。

选择以面向对象的方式观察世界,会产生一系列的问题:什么是好的面向对象的体系结构?项目会创造出什么样的制品?谁创造它们?怎样度量它们?

【第2章讨论这些问题。】

对面向对象系统进行可视化、详述、构造和文档化正是统一建模语言(UML)的目的。

第2章 UML介绍

本章内容

UML概述

理解UML的3个步骤

软件体系结构

软件开发过程

统一建模语言(Unified Modeling Language,UML)是一种绘制软件蓝图的标准语言。可以用UML对软件密集型系统的制品进行可视化、详述、构造和文档化。

从企业信息系统到基于Web的分布式应用,乃至硬实时嵌入式系统,都适合用UML来建模。UML是一种富有表达力的语言,可以描述开发所需要的各种视图,然后以此为基础来部署系统。虽然 UML 的表达力很丰富,但理解和使用它并不困难。要学习使用 UML,一个有效的出发点是形成该语言的概念模型,这要求学习3个要素:UML的基本构造块、支配这些构造块如何放置在一起的规则以及运用于整个语言的一些公共机制。

UML仅仅是一种语言,因此仅仅是软件开发方法的一部分。UML是独立于过程的,但最好把它用于以用况为驱动、以体系结构为中心、迭代和增量的过程。

2.1 UML概述

UML是一种对软件密集型系统的制品进行下述工作的语言:

可视化;

详述;

构造;

文档化。

2.1.1 UML是一种语言

语言提供了用于交流的词汇表和在词汇表中组合词汇的规则,而建模语言的词汇表和规则注重于对系统进行概念上和物理上的描述,因而像UML这样的建模语言是用于软件蓝图的标准语言。

建模是为了产生对系统的理解。只用一个模型是不够的,相反,为了理解系统(除非是非常微小的系统)中的各种事物,经常需要多个相互联系的模型。对于软件密集型系统,就需要这样一种语言,它贯穿于软件开发的生命期,表达系统体系结构的各种不同视图。

【第1章讨论建模的基本原理。】

像UML这样的语言的词汇表和规则可以告诉你如何创建或理解形式良好的模型,但它没有说明应该在什么时候创建什么样的模型,因为这是软件开发过程的工作。一个定义良好的过程将指导你决定生产什么制品,由什么样的活动和人员来创建与管理这些制品,怎样采用这些制品从整体上去度量和控制项目。

2.1.2 UML是一种用于可视化的语言

对于很多程序员来说,从考虑实现到产生程序代码,其间没有什么距离可言,就是思考和编码。事实上,对有些事情的处理最好就是直接编码。使用文本是既省事又直接的书写表达式和算法的方式。

在这种情况下,程序员仍然要做一些建模,虽然只是在内心里这样做。他们甚至可以在白板或餐巾纸上草拟出一些想法。然而,这样做存在几个问题。第一,别人对这些概念模型容易产生错误的理解,因为并不是每个人都使用相同的语言。一种典型的情况是,假设项目开发单位建立了自己的语言,如果你是外来者或是加入项目组的新人,就难以理解该单位在做什么事。第二,除非建立了模型(不仅仅是文字的编程语言),否则就不能够理解软件系统中的某些事情。例如,阅读一个类层次的所有代码,虽可推断出它的含义,但不能直接领会它。类似地,在基于 Web的系统中研究系统的代码,虽可推断出对象的物理分布和可能迁移,但也不能直接领会它。第三,如果一个开发者删节了代码而没有写下他头脑中的模型,一旦他另谋高就,那么这些信息就会永远丢失,最好的情况也只能是通过实现而部分地重建。

用UML建模可解决第三个问题:清晰的模型有利于交流。

对有些事物最好是用文字建模,而对有些事物又最好是用图形建模。的确,在所有引人关注的系统中都有一些用编程语言难以描绘的结构。UML 正是这样的图形化语言。这一点针对前面谈到的第二个问题。

UML不仅只是一组图形符号。确切地讲,UML表示法中的每个符号都有明确语义。这样,一个开发者可以用UML绘制一个模型,而另一个开发者(甚至工具)可以无歧义地解释这个模型。这一点针对前面谈到的第一个问题。

【UML的完整语义在The Unified Modeling Language Reference一书中讨论。】

2.1.3 UML是一种可用于详细描述的语言

在此处,详细描述意味着所建的模型是精确的、无歧义的和完整的。特别是,UML 适于对所有重要的分析、设计和实现决策进行详细描述,这些是软件密集型系统在开发和部署时所必需的。

2.1.4 UML是一种用于构造的语言

UML 不是一种可视化的编程语言,但用 UML 描述的模型可与各种编程语言直接相关联。这意味着一种可能性,即可把用UML描述的模型映射成编程语言,如Java、C++和Visual Basic等,甚至映射成关系数据库的表或面向对象数据库的持久存储。对一个事物,如果表示为图形方式最为恰当,则用UML,而如果表示为文字方式最为恰当,则用编程语言。

这种映射允许进行正向工程——从 UML 模型到编程语言的代码生成,也可以进行逆向工程——由编程语言代码重新构造UML模型。逆向工程并不是魔术。除非对实现中的信息编码,否则从模型到代码生成将会丢失信息。逆向工程需要工具支持和人的干预。把正向代码生成和逆向工程这两种方式结合起来就可以产生双向工程,这意味着既能在图形视图下工作,又能在文字视图下工作,只要用工具来保持二者的一致性即可。

【本书的第二部分和第三部分讨论对系统的结构建模。】

除了直接映射以外,UML 具有丰富的表达力,而且无歧义性,这允许直接执行模型、模拟系统以及对运行系统进行操纵。

【本书的第四部分和第五部分讨论对系统的行为建模。】

2.1.5 UML是一种用于文档化的语言

一个健康的软件组织除了生产可执行代码之外,还要给出各种制品。这些制品包括(但不限于):

需求;

体系结构;

设计;

源代码;

项目计划;

测试;

原型;

发布。

依赖于开发文化,一些制品做得或多或少地比另一些制品要正规些。这些制品不但是项目交付时所要求的,而且无论是在开发期间还是在交付使用后对控制、度量和理解系统也是关键的。

UML适于建立系统体系结构及其所有细节的文档。UML还提供了用于表达需求和用于测试的语言。此外,UML提供了对项目计划活动和发布管理活动进行建模的语言。

2.1.6 在何处能使用UML

UML主要用于软件密集型系统。在下列领域中已经有效地应用了UML:

企业信息系统;

银行与金融服务;

电信;

运输;

国防/航天;

零售;

医疗电子;

科学;

基于Web的分布式服务。

UML 不限于对软件建模。事实上,它的表达能力对非软件系统建模也是足够的。例如,法律系统的工作流程、病人保健系统的结构和行为、飞机战斗系统中的软件工程以及硬件设计等。

2.2 UML的概念模型

为了理解UML,需要形成该语言的概念模型,这要求学习建模的3个要素:UML的基本构造块、支配这些构造块如何放在一起的规则和一些运用于整个UML的公共机制。如果掌握了这些思想,就能够读懂UML模型,并能建立一些基本模型。当有了较丰富的应用UML的经验时,就能够在这些概念模型之上使用更高深的语言特征进行构造。

2.2.1 UML的构造块

UML的词汇表包含下面3种构造块:

(1)事物;

(2)关系;

(3)图。

事物是对模型中首要成分的抽象;关系把事物结合在一起;图聚集了相关的事物。

1.UML中的事物

在UML中有4种事物:

(1)结构事物;

(2)行为事物;

(3)分组事物;

(4)注释事物。

这些事物是UML中基本的面向对象的构造块,用它们可以写出形式良好的模型。

2.结构事物

结构事物(structural thing)是UML模型中的名词。它们通常是模型的静态部分,描述概念元素或物理元素。结构事物总称为类目(classifier)。

第一,(class)是对一组具有相同属性、相同操作、相同关系和相同语义的对象的描述。类实现一个或多个接口。在图形上,把类画成一个矩形,矩形中通常包括类的名称、属性和操作,如图2-1所示。

【第4章和第9章讨论类。】

第二,接口(interface)是一组操作的集合,其中的每个操作描述了类或构件的一个服务。因此,接口描述了元素的外部可见行为。一个接口可以描述一个类或构件的全部行为或部分行为。接口定义了一组操作规约(即操作的特征标记),而不是操作的实现。接口的声明看上去像一个类,在名称的上方标注着关键字«interface»;除非有时用来表示常量,否则不需要属性。然而,接口很少单独出现。如图2-2 所示,把由类提供的对外接口表示成用线连接到类框的一个小圆圈,把类向其他类请求的接口表示成用线连接到类框的半个小圆圈。

【第11章讨论接口。】

第三,协作(collaboration)定义了一个交互,它是由一组共同工作以提供某种协作行为的角色和其他元素构成的一个群体,这些协作行为大于所有元素的各自行为的总和。协作具有结构、行为和维度。一个给定的类或对象可以参与几个协作。这些协作因而表现了系统构成模式的实现。在图形上,把协作画成虚线椭圆,有时仅包含它的名称,如图2-3所示。

【第28章讨论协作。】

第四,用况(use case)是对一组动作序列的描述,系统执行这些动作将产生对特定的参与者有价值而且可观察的结果。用况用于构造模型中的行为事物。用况是通过协作实现的。在图形上,把用况画成实线椭圆,通常仅包含它的名称,如图2-4所示。

【第17章讨论用况。】

剩余的3种事物——主动类、构件和结点,都和类相似,就是说它们也描述了一组具有相同属性、操作、关系和语义的实体。然而,这3种事物与类的不同点也不少,而且对面向对象系统的某些方面的建模是必要的,因此对这几个术语需要单独处理。

第五,主动类(active class)是这样的类,其对象至少拥有一个进程或线程,因此它能够启动控制活动。主动类的对象所表现的元素的行为与其他元素的行为并发,除了这一点之外,它和类是一样的。在图形上,把主动类绘制成类图符,只是它的左右外框是双线,通常它包含名称、属性和操作,如图2-5所示。

【第23章讨论主动类。】

第六,构件(component)是系统设计的模块化部件,将实现隐藏在一组外部接口背后。在一个系统中,共享相同接口的构件可以相互替换,只要保持相同的逻辑行为即可。可以通过把部件和连接件接合在一起表示构件的实现;部件可以包括更小的构件。在图形上,构件的表示很像类,只是在其右上角有一个特殊的图标,如图2-6所示。

【第15章讨论构件和内部结构。】

剩下的两种元素是制品和结点,它们也是不同的。它们表示物理事物,而前6种元素表示概念或逻辑事物。

第七,制品(artifact)是系统中物理的而且可替换的部件,它包括物理信息(“比特”)。在一个系统中,会遇到不同类型的部署制品,如源代码文件、可执行程序和脚本。制品通常代表对源码信息或运行时信息的物理打包。在图形上,把制品画成一个矩形,在其名称的上方标注着关键字«artifact»,如图2-7所示。

【第26章讨论制品。】

第八,结点(node)是在运行时存在的物理元素,它表示一个计算机资源,通常至少有一些记忆能力,还经常具有处理能力。一组构件可以驻留在一个结点内,也可以从一个结点迁移到另一个结点。在图形上,把结点画成一个立方体,通常在立方体中只写它的名称,如图2-8所示。

【第27章讨论结点。】

这些元素——类、接口、协作、用况、主动类、构件、制品和结点,是UML模型中可以包含的基本结构事物。它们也有变体,如参与者、信号、实用程序(几种类)、进程和线程(两种主动类)、应用、文档、文件、库、页和表(几种制品)等。

3.行为事物

行为事物 behavioral thing)是UML模型的动态部分。它们是模型中的动词,代表了跨越时间和空间的行为。共有3类主要的行为事物。

第一,交互(interaction)是这样一种行为,它由在特定语境中共同完成一定任务的一组对象或角色之间交换的消息组成。一个对象群体的行为或者单个操作的行为可以用一个交互来描述。交互涉及一些其他元素,包括消息、动作和连接件(对象间的连接)。在图形上,把消息画成一条有方向的直线,通常在其上总是带有操作名,如图2-9所示。

【第17章讨论用于模型中构造行为事物的用况,在第16章讨论交互。】

第二,状态机(state machine)是这样一种行为,它描述了一个对象或一个交互在生命期内响应事件所经历的状态序列以及它对这些事件做出的响应。单个类或一组类之间协作的行为可以用一个状态机来描述。状态机涉及到一些其他元素,包括状态、转移(从一个状态到另一个状态的流)、事件(触发转换的事物)和活动(对一个转移的响应)。在图形上,把状态画成一个圆角矩形,通常在其中含有状态的名字及其子状态(如果有的话),如图2-10所示。

【第22章讨论状态机。】

第三,活动(activity)是这样一种行为,它描述了计算过程执行的步骤序列。交互所注重的是一组进行交互的对象,状态机所注重的是一定时间内一个对象的生命周期,活动所注重的是步骤之间的流而不关心哪个对象执行哪个步骤。活动的一个步骤称为一个动作。在图形上,把动作画成一个圆角矩形,在其中含有指明其用途的名字,如图2-11 所示。状态和动作靠不同的语境得以区别。

交互、状态机和活动这3种元素是UML模型中可能包含的基本行为事物。在语义上,这些元素通常与各种结构元素(主要是类、协作和对象)相关。

4.分组事物

分组事物(grouping thing)是UML模型的组织部分。它们是一些由模型分解成的“盒子”。主要的分组事物是包。

(package)是用于对设计本身进行组织的通用机制,与类不同,它是用来组织实现构造物的。结构事物、行为事物甚至其他的分组事物都可以放进包内。包不像构件(构件在运行时存在),它纯粹是概念上的(即它仅在开发时存在)。在图形上,把包画成带标签的文件夹(一个左上角带有一个小矩形的大矩形),在矩形中通常仅含有包的名称,有时还含有其内容,如图2-12所示。

【第12章讨论包。】

包是用来组织UML模型的基本分组事物。它也有变体,如框架、模型和子系统(它们是包的不同种类)。

5.注释事物

注释事物(annotational thing)是UML模型的解释部分。这些注释事物用来描述、说明和标注模型中的任何元素。有一种主要的注释事物,称为注解。注解(note)是依附于一个元素或一组元素之上对它进行约束或解释的简单符号。在图形上,把注解画成一个右上角是折角的矩形,其中带有文字或图形解释,如图2-13所示。

【第6章讨论注解。】

该元素是可以包含在UML模型中的基本注释事物。通常可以用注解中所含的约束或解释来修饰图,最好是把注释表示成形式或非形式化的文本。这种元素也有变体,例如需求(从模型的外部来描述一些想得到的行为)。

6.UML中的关系

在UML中有4种关系:

(1)依赖;

(2)关联;

(3)泛化;

(4)实现。

这些关系是UML的基本关系构造块,用它们可以写出形式良好的模型。

第一,依赖(dependency)是两个模型元素间的语义关系,其中一个元素(独立元素)发生变化会影响另一个元素(依赖元素)的语义。在图形上,把依赖画成一条可能有方向的[2]虚线,有时还带有一个标记,如图2-14所示。

【第5章和第10章讨论依赖。】

第二,关联(association)是类之间的结构关系,它描述了一组链,链是对象(类的实例)之间的连接。聚合是一种特殊类型的关联,它描述了整体和部分间的结构关系。在图形上,把关联画成一条实线,它可能有方向,有时还带有一个标记,而且它还经常含有诸如多重性和端名这样的修饰,如图2-15所示。

【第5章和第10章讨论关联。】

第三,泛化(generalization)是一种特殊/一般关系,其中特殊元素(子元素)基于一般元素(父元素)而建立。用这种方法,子元素共享了父元素的结构和行为。在图形上,把泛化关系画成一条带有空心箭头的实线,该实线指向父元素,如图2-16所示。

【第5章和第10章讨论泛化。】

第四,实现(realization)是类目之间的语义关系,其中一个类目指定了由另一个类目保证执行的合约。在两种地方会遇到实现关系:一种是在接口和实现它们的类或构件之间;另一种是在用况和实现它们的协作之间。在图形上,把实现关系画成一条带有空心箭头的虚线,它是泛化和依赖关系两种图形的结合,如图2-17所示。

【第10章讨论实现关系。】

这4种元素是UML模型中可以包含的基本关系事物。它们也有变体,例如,精化、跟踪、包含和扩展。

7.UML中的图

图(diagram)是一组元素的图形表示,大多数情况下把图画成顶点(代表事物)和弧(代表关系)的连通图。为了对系统进行可视化,可以从不同的角度画图,这样一个图是对系统的投影。对所有的系统(除非很微小的系统)而言,图是系统组成元素的省略视图。有些元素可以出现在所有图中,有些元素可以出现在一些图中(很常见),还有些元素不能出现在图中(很罕见)。在理论上,图可以包含事物及其关系的任何组合。然而在实际中仅出现少量的常见组合,它们与组成软件密集型系统的体系结构的5种最有用的视图相一致。由于这个原因,UML包括13种这样的图:

【在本章后面讨论体系结构的5种视图。】

(1)类图;

(2)对象图;

(3)构件图;

(4)组合结构图;

(5)用况图;

(6)顺序图[3]

(7)通信图;

(8)状态图;

(9)活动图;

(10)部署图;

(11)包图;

(12)定时图;

(13)交互概览图。

类图(class diagram)展现了一组类、接口、协作和它们之间的关系。在面向对象系统的建模中所建立的最常见的图就是类图。类图给出系统的静态设计视图。包含主动类的类图给出系统的静态进程视图。构件图是类图的变体。

【第8章讨论类图。】

对象图(object diagram)展现了一组对象以及它们之间的关系。对象图描述了在类图中所建立的事物的实例的静态快照。和类图一样,这些图给出系统的静态设计视图或静态进程视图,但它们是从真实案例或原型案例的角度建立的。

【第14章讨论对象图。】

构件图(component diagram)展现了一个封装的类和它的接口、端口以及由内嵌的构件和连接件构成的内部结构。构件图用于表示系统的静态设计实现视图。对于由小的部件构建大的系统来说,构件图是很重要的(UML 将构件图和适用于任意类的组合结构图区分开来,但由于构件和结构化类之间的差别微不足道,所以一起讨论它们)。

【第15章讨论构件图和内部结构。】

用况图(use case diagram)展现了一组用况、参与者(一种特殊的类)及它们之间的关系。用况图给出系统的静态用况视图。这些图在对系统的行为进行组织和建模上是非常重要的。

【第18章讨论用况图。】

顺序图和通信图都是交互图。交互图(interaction diagram)展现了一种交互,它由一组对象或角色以及它们之间可能发送的消息构成。交互图专注于系统的动态视图。顺序图(sequence diagram)是强调消息的时间次序的交互图;通信图(communication diagram)也是一种交互图,它强调收发消息的对象或角色的结构组织。顺序图和通信图表达了类似的基本概念,但每种图强调概念的不同视角,顺序图强调时间次序,通信图强调消息流经的数据结构。定时图(不包含在本书中)展现了消息交换的实际时间。

【第19章讨论交互图。】

状态图(state diagram)展现了一个状态机,它由状态、转移、事件和活动组成。状态图展现了对象的动态视图。它对于接口、类或协作的行为建模尤为重要,而且它强调由事件引发的对象行为,这非常有助于对反应式系统建模。

【第25章讨论状态图。】

活动图(activity diagram)将进程或其他计算的结构展示为计算内部一步一步的控制流和数据流。活动图专注于系统的动态视图。它对于系统的功能建模特别重要,并强调对象间的控制流程。

【第20章讨论活动图。】

部署图(deployment diagram)展现了对运行时的处理结点以及在其中生存的构件的配置。部署图给出了体系结构的静态部署视图。通常一个结点包含一个或多个制品。

【第31章讨论部署图。】

制品图(artifact diagram)展现了计算机中一个系统的物理结构。制品包括文件、数据库和类似的物理比特集合。制品常与部署图一起使用。制品也展现了它们实现的类和构件。(UML把制品图视为部署图的变体,但我们分别地讨论它们。)

【第30章讨论制品图。】

包图(package diagram)展现了由模型本身分解而成的组织单元以及它们的依赖关系。

【第12章讨论包图。】

定时图(timing diagram)是一种交互图,它展现了消息跨越不同对象或角色的实际时间,而不仅仅是关心消息的相对顺序。交互概览图(interaction overview diagram)是活动图和顺序图的混合物。这些图有特殊的用法,本书不做讨论,更多的细节可参考The Unified Modeling Language Reference Manual。

并不限定仅使用这几种图,开发工具可以利用UML来提供其他种类的图,但到目前为止,这几种图在实际应用中是最常用的。

2.2.2 UML规则

不能简单地把 UML 的构造块按随机的方式堆放在一起。像任何语言一样,UML 有一套规则,这些规则描述了一个形式良好的模型应该是什么样。形式良好的模型应该在语义上是自我一致的,并且与所有的相关模型协调一致。

UML有自己的语法和语义规则,用于:

命名——为事物、关系和图起的名字;

范围——使名字具有特定含义的语境;

可见性——这些名字如何让其他成分看见和使用;

完整性——事物如何正确、一致地相互联系;

执行——运行或模拟一个动态模型意味着什么。

在软件密集型系统的开发期间所建造的模型往往需要发展变化,并可以由许多人员以不同的方式、在不同的时间进行观察。由于这个原因,下述的情况是常见的,即开发组不但会建造一些形式良好的模型,也会建造一些像下面这样的模型:

省略——隐藏某些元素以简化视图;

不完全——可能遗漏了某些元素;

不一致——模型的完整性得不到保证。

在软件开发的生命期内,随着系统细节的展开和变动,不可避免地要出现这样一些不太规范的模型。UML 的规则鼓励(不是强迫)专注于最重要的分析、设计和实现问题,这将促使模型随着时间的推移而具有良好的结构。

2.2.3 UML中的公共机制

通过与具有公共特征的模式取得一致,可以使一座建筑更为简单和更为协调。房子可以按一定的结构模式(它定义了建筑风格)建造成维多利亚式的或法国乡村式的。对于UML也是如此。由于在UML中有4种贯穿整个语言且一致应用的公共机制,因此使得UML变得较为简单。这4种机制是:

(1)规约;

(2)修饰;

(3)通用划分;

(4)扩展机制。

1.规约

UML 不仅仅是一种图形语言。实际上,在它的图形表示法的每部分背后都有一个规约,这个规约提供了对构造块的语法和语义的文字叙述。例如,在类的图符背后有一个规约,它提供了对该类所拥有的属性、操作(包括完整的特征标记)和行为的全面描述;在视觉上,类的图符可能仅展示了这个规约的一小部分。此外,可能存在着该类的另一个视图,其中提供了一个完全不同的部件集合,但是它仍然与该类的基本规约相一致。UML 的图形表示法用来对系统进行可视化;UML 的规约用来说明系统的细节。假定把二者分开,就可能进行增量式的建模。这可以通过以下方式完成:先画图,然后再对这个模型的规约增加语义,或直接创建规约,也可能对一个已经存在的系统进行逆向工程,然后再创建作为这些规约的投影的图。

UML 的规约提供了一个语义底版,它包含了一个系统的各个模型的所有部分,各部分以一致的方式相互联系。因此,UML 的图只不过是对底版的简单视觉投影,每一个图展现了系统的一个特定的关注方面。

2.修饰

UML中的大多数元素都有唯一而直接的图形表示符号,这些图形符号对元素的最重要的方面提供了可视化表示。例如,特意把类的符号设计得容易画出,这是因为在面向对象系统建模中,类是最常用的元素;类的图形符号展示了类的最重要方面,即它的名称、属性和操作。

【第6章讨论注解和其他修饰。】

对类的规约可以包含其他细节,例如,它是否为抽象类,或它的属性和操作是否可见。可以把很多这样的细节表示为图形或文字修饰,放到类的基本矩形符号上。例如,图2-18 表示的是一个带有修饰的类,图中表明这个类是一个抽象类,有两个公共操作、一个受保护操作和一个私有操作。

UML表示法中的每一个元素都有一个基本符号,可以把各种修饰细节加到这个符号上。

3.通用划分

在对面向对象系统建模中,通常有几种划分方式。

第一种方式是对类和对象的划分。类是一种抽象,对象是这种抽象的一个具体表现。在UML中,可以对类和对象建立模型,如图2-19所示。在图形上,UML是这样区分对象的:采用与类同样的图形符号来表示对象,并且在对象名的下面画一道线。

【第13章中讨论对象。】

在这个图中,有一个名称为Customer的类,它有3个对象,分别为Jan(它被明确地标记为Customer的对象),:Customer(匿名的Customer对象)和Elyse(它在规约中被说明为一种Customer对象,尽管在这里没有明确地表示出来)。

UML的每一个构造块几乎都存在像类/对象这样的二分法。例如,可以有用况和用况执行、构件和构件实例、结点和结点实例等。

第二种方式是接口和实现的分离。接口声明了一个合约,而实现则表示了对该合约的具体实施,它负责如实地实现接口的完整语义。在UML中,既可以对接口建模又可以对它们的实现建模,如图2-20所示。

【第11章讨论接口。】

在这个图中,有一个名称为SpellingWizard.dll的构件,它实现了接口IUnknown和接口ISpelling,并且还需要一个由其他构件提供的名为IDictionary的接口。

几乎每一个UML的构造块都有像接口/实现这样的二分法。例如,用况和实现它们的协作,操作和实现它们的方法。

第三种方式是类型和角色的分离。类型声明了实体的种类(如对象、属性或参数),角色描述了实体在语境中的含义(如类、构件或协作等)。任何作为其他实体结构中的一部分的实体(例如属性)都具有两个特性:从它固有的类型派生出一些含义,从它在语境中的角色派生出一些含义(如图2-21所示)。

4.扩展机制

UML 提供了一种绘制软件蓝图的标准语言,但是一种闭合的语言即使表达能力再丰富,也难以表示出各种领域中的各种模型在不同时刻所有可能的细微差别。由于这个原因,UML 是目标开放的,使人们能够以受控的方式来扩展该语言。UML的扩展机制包括:

衍型;

标记值;

约束。

衍型(stereotype)扩展了UML的词汇,可以用来创造新的构造块,这个新构造块既是从现有的构造块派生的,但是针对专门的问题。例如,假设正在使用一种编程语言,如Java或C++,经常要对“异常事件”建模。在这些语言里,“异常事件”就是类,只是用很特殊的方法进行了处理。通常可能只想允许抛出和捕捉异常事件,没有其他要求。此时可以让异常事件在模型中成为“一等公民”——可以像对待基本构造块一样对待它们,只要用一个适当的衍型来标记它们即可。请看图2-22中的类Overflow。

【第6章讨论UML的扩展机制。】

标记值(tagged value)扩展了UML衍型的特性,可以用来创建衍型规约的新信息。例如,如果在制作以盒装形式销售的产品,随着时间的推移,它经过了多次发行,那么经常会想要跟踪产品的版本和对产品做关键摘要的作者。版本和作者不是UML的基本概念,通过引入新的标记值,可以把它们加到像类那样的任何构造块中去。例如,在图2-22中,在类EventQueue上明确标记了版本和作者,这样就对该类进行了扩展。

约束(constraint)扩展了UML构造块的语义,可以用来增加新的规则或修改现有的规则。例如,可能想约束类 EventQueue,以使所有的增加都按序排列。如图2-22 所示,对操作 add增加了一个约束,即{ordered},以明确标示这一规则。

总的来说,这3种扩展机制允许根据项目的需要来塑造和培育UML。这些机制也使得UML适合于新的软件技术(例如,很可能出现的功能更强的分布式编程语言)。可以增加新的构造块,修改已存在的构造块的规约,甚至可以改变它们的语义。当然,以受控的方式进行扩展是重要的,这样可以不偏离UML的目标——信息交流。

2.3 体系结构

可视化、详述、构造和文档化一个软件密集型系统,要求从几个角度去观察系统。各种人员——最终用户、分析人员、开发人员、系统集成人员、测试人员、技术资料作者和项目管理者——各自带着项目的不同日程,在项目的生命周期内各自在不同的时间、以不同的方式来看系统。系统体系结构或许是最重要的制品,它可以驾驭不同的视点,并在整个项目的生命周期内控制对系统的迭代和增量式开发。

【第1章讨论需要从不同的角度观察复杂系统。】

体系结构是一组有关下述内容的重要决策:

软件系统的组织;

对组成系统的结构元素及其接口的选择;

像元素间的协作所描述的那样的行为;

将这些结构元素和行为元素组合到逐步增大的子系统中;

指导这种组织的体系结构风格:静态和动态元素以及它们的接口、协作和组成。

软件体系结构不仅关心结构和行为,而且还关心用法、功能、性能、弹性、复用、可理解性、经济与技术约束及其折中,以及审美的考虑。

如图2-23所示,最好用5个互连的视图来描述软件密集型系统的体系结构。每一个视图是在一个特定的方面对系统的组织和结构进行的投影。

【第32章讨论对系统的体系结构建模。】

系统的用况视图(use case view)由描述可被最终用户、分析人员和测试人员看到的系统行为的用况组成。用况视图实际上没有描述软件系统的组织,而是描述了形成系统体系结构的动力。在UML中,该视图的静态方面由用况图表现;动态方面由交互图、状态图和活动图表现。

系统的设计视图(design view)包含了类、接口和协作,它们形成了问题及其解决方案的词汇。这种视图主要支持系统的功能需求,即系统应该提供给最终用户的服务。在UML中,该视图的静态方面由类图和对象图表现;动态方面由交互图、状态图和活动图表现。类的内部结构图特别有用。

系统的交互视图(interaction view)展示了系统的不同部分之间的控制流,包括可能的并发和同步机制。该视图主要针对性能、可伸缩性和系统的吞吐量。在UML中,对该视图的静态方面和动态方面的表现与设计视图相同,但着重于控制系统的主动类和在它们之间流动的消息。

系统的实现视图(implementation view)包含了用于装配与发布物理系统的制品。这种视图主要针对系统发布的配置管理,它由一些独立的文件组成;这些文件可以用各种方法装配,以产生运行系统。它也关注从逻辑的类和构件到物理制品的映射。在UML中,该视图的静态方面由构件图表现,动态方面由交互图、状态图和活动图表现。

系统的部署视图(deployment view)包含了形成系统硬件拓扑结构的结点(系统在其上运行)。这种视图主要描述组成物理系统的部件的分布、交付和安装。在UML中,该视图的静态方面由部署图表现,动态方面由交互图、状态图和活动图表现。

这5种视图中的每一种都可单独使用,使不同的人员能专注于他们最为关心的体系结构问题。这5种视图也会相互作用,如部署视图中的结点拥有实现视图的构件,而这些构件又表示了设计视图和交互视图中的类、接口、协作以及主动类的物理实现。UML允许表达这5种视图中的任何一种。

2.4 软件开发生命周期

UML 在很大程度上是独立于过程的,这意味着它不依赖于任何特殊的软件开发生命周期。然而,为了从UML中得到最大的收益,应该考虑这样的过程,它是:

用况驱动的;

以体系结构为中心的;

迭代的和增量的。

【在附录B中概述了Rational统一过程,对该过程的更完整处理在The Unified Software Development Process一书以及The Rational Unified Process中讨论。】

用况驱动(use case driven)意味着把用况作为一种基本的制品,用于建立所要求的系统行为、验证和确认系统的体系结构、测试以及在项目组成员间进行交流。

以体系结构为中心(architecture-centric)意味着以系统的体系结构作为一种基本制品,对被开发的系统进行概念化、构造、管理和演化。

迭代过程(iterative process)是这样一种过程,它涉及到对一连串可执行的发布的管理。增量过程(incremental process)是这样一种过程,它涉及到系统体系结构的持续集成,以产生各种发布,每个新的发布都比上一个发布有所改善。总的来讲,迭代和增量的过程是风险驱动的(risk-driven),这意味着每个新的发布都致力于处理和降低对于项目成功影响最为显著的风险。

这种用况驱动的、以体系结构为中心的、迭代/增量的过程可以分成几个阶段。阶段(phase)是过程的两个主要里程碑之间的时间跨度,在阶段中将达到一组明确的目标,完成一定的制品,并做出是否进入到下一阶段的决策。如图2-24所示,在软件开发生命周期内有4个阶段:初始、细化、构造和移交。在图中,按这些阶段对工作流进行了划分,并显示了它们的焦点随时间的推移而变化的程度。

初始(inception)是这个过程的第一个阶段。在此阶段,萌发的开发想法经过培育要达到这样一个目标:至少要在内部奠定足够的基础,以保证能够进入到细化阶段。

细化(elaboration)是这个过程的第二个阶段。在此阶段定义产品需求和体系结构。在这个阶段,将明确系统需求,按其重要性排序并划定基线。可以按一般的描述,也可以按精确的评价准则来排列系统的需求,每个需求都说明了特定的功能或非功能的行为,并为测试提供了基础。

构造(construction)是这个过程的第三个阶段,在此阶段软件从可执行的体系结构基线发展到准备移交给用户。针对项目的商业需要,这里也要不断地对系统的需求,特别是对系统的评价准则进行检查,并要适当地分配资源,以主动地降低项目的风险。

移交(transition)是这个过程的第四个阶段,在此阶段把软件交付给用户。在这个阶段,软件开发过程很少能结束,还要继续改善系统,根除错误,增加早期发布未能实现的特性。

使得这个过程与众不同,并贯穿所有 4个阶段的要素是迭代。迭代(iteration)是一组明确的工作任务,具有产生能运行、测试和评价的可执行系统的基准计划和评价准则。可执行系统无须向外发布。因为迭代产生可执行的产品,所以可以判断进展并在每次迭代后可重新估计风险。这意味着,软件开发生命周期具有以下特征:持续地发布系统体系结构的可执行版本,而且在每步迭代后可中途进行修改,以减少潜在的风险。正是因为强调将体系结构作为一个重要的制品,UML非常注重对系统体系结构的不同视图进行建模。

相关图书

现代软件工程:如何高效构建软件
现代软件工程:如何高效构建软件
UML基础、案例与应用(第3版)(修订版)
UML基础、案例与应用(第3版)(修订版)
持续交付:发布可靠软件的系统方法(英文版)
持续交付:发布可靠软件的系统方法(英文版)
团队软件过程(修订版)
团队软件过程(修订版)
掌握需求过程(第3版)
掌握需求过程(第3版)
术以载道——软件过程改进实践指南
术以载道——软件过程改进实践指南

相关文章

相关课程