1997年的最后一个季度,我在教一些来自不同项目的开发者使用UML作面向对象分析与实际。这些项目涉及许多应用领域包括零售货架空间治理,临床药物实验,移动电话等。开发语言包括Visual Basic, C++, Java, DB2还有其他。通过我们公司的用例驱动统一对象建模过程(是建立在Booch, Jacobson, and Rumbaugh方法的基础之上的)来从几个方面介绍UML符号如何更好得满足不同项目的需求。为如何使用UML提供了实际的指导。
UML的符号比较多(可能太多)而且足够灵活能适应大范围项目的需求。为了成功使用UML,在使用的过程中必须流程化。不同的项目需要不同的内容。项目中使用UML符号的哪些具体元素取决于项目的本质(使用关系数据库客户端/服务器端或实时嵌入式)及要使用的开发语言。使用JAVA或Smalltalk时一些具体的C++设计组件将不会被使用;假如使用VB,你可能想避免使用更多的泛化和继续。有时,纯粹的建模组件可能太庞大了,尤其对那些刚开始接触面向对象分析和设计的学生来说。但是,好消息是几乎任何事情都可以使用UML来建模来实现。有很多建模组件可供使用。
You Still Need a Process过程仍然需要
UML本身仅仅是一种符号,为了创建有效的模型,仍然需要一个建模过程。使用UML有很多种建模方法;建模语言本身并不描述过程。在UML产生的几年前,我们一直把作了微小变化的Objectory过程(从Ivar Jacobson的 《面向对象软件工程:一个用例驱动方法》而来,Addison-Wesley, 1992)作为Booch/Rumbaugh/Jacobson的综合来授课,并取得了成功。我们的方法将重点放在了区分更高层次的静态模型(域模型),同时也产生用例。然后我们精炼出静态模型,在开发用例和动态模型时反复精练。
或者你更倾向于使用Objectory,对象模型方法,我们的ICONIX统一对象模型过程,或其他一些方法。在从事建模工作之前,理解UML不是一个过程是重要的。让项目组处于同一个开发阶段尤其重要。让项目组对UML有统一的理解使建模成功的保证。UML的规模(文档符号的庞大相对于过程而言)很轻易陷入“分析麻痹”。关注项目组通过UML符号对过程的统一理解,能让建模更轻易。
Legacy Methods Are Important 过去的方法依然重要
我的大部分学生会问我理解Booch, Jacobson, and Rumbaugh过去的方法是否仍然很重要。我的答案是非常重要。就像知道电流设计并没有排除知道电路理论一样,虽然UML符号而不排除理解对象建模理论的必要性。自从UML代表了Jacobson, Booch, and Rumbaugh三人方法的综合,但早期的方法是信息的来源。
Keep It Simple保持简单
让一个项目组有效的使用UML是有难度的。项目组成员对于面向对象分析和设计以及UML的理解层次各自不同。开始之前统一培训是不错的方法,培训需要认真考虑项目组每个成员的背景及项目的非凡要求。最重要的决定在于课程表的明智选择和指导老师在工作期间的调整。
在学习UML中需要记住的一点是我们并不需要使用每一个存在的组件。让过程尽量简单化。流程化一个项目的文档和建模方法对项目的进行有非凡的作用。
用UML建模和有时和座在一大堆事物面前很相似,开始吃之前就有不能吃完盘子里面的所有食物的想法可能毁了你的食欲。同样的现象可能发生在UML建模过程中。用完全具体的动态模型描述系统的每一个用例,而不得不创建一系列完整的时序图、协作图、状态图、部署图,用例和类图的想法可能会让一个团队完全脱离面向对象分析和设计。
在一个给定的建模方法中决定使用哪一个组件简单同样是要考虑的。举例来说,在一个用例图上同时使用USES 和EXTENDS真的有必要吗?或者我们只需要使用USES?我的经验是流程化的东西越多,建模成功的可能性越大。
Write the User Manual Before You Design the Classes设计类之前写使用手册
写程序的一条老的规矩是在写代码之前写使用手册。在我学习的时候我认为这是一条好的建议,并且到今天为止我仍然认为是好的建议。在面向过程的年代和面向对象方法的早期,这条规矩很少被遵从。在用例驱动建模方法中,Jacobson把这个规律编写成一系列的步骤,通过这些步骤可以为对象服务并且能用UML描述。每一个步骤建立在上一个步骤的基础之上,形成一个可以跟踪的方法,直道最后,治理能加强这个方法把它作为一个设计范例并且确认在分析和设计的过程中能被遵守。
基础层次的人理解Objectory和用例驱动对象建模的本质的简单方法是:在设计类之前写使用手册。大脑里一直有这个想法将会帮助你在UML的迷宫里穿越静态和动态的建模符号。每一个用例代表着用户手册的一部分,并且应该按着“用例分析的目的是产生对象模型”的方式写。
Organize Use Cases into Packages用例打包
一旦你预备为你的系统的每一个用例书写使用手册的时候,你将很快会意识到需要更高层次的把用例组装起来。UML答应你把用例打包。这些可以用文件标签代表。每一个包至少应该包括一个用例图,这个图可以作为一个上下文图,它可能把设计阶段每个用例的动态视图和用例描述联系起来。有一些项目从高层次的包分割开始。这些分割并不总是代表最终的分割,有时是很好的开始起点。
Use the Objectory Stereotypes使用Objectory模板
整个设计过程从用例中分离出来,表明注重描述它们是“正确“的方法。同时在需求分析和业务过程建模中用例作为一种备选方案正越来越受到欢迎。不同形式的用例建模有一些不同的向导,我碰到的大部分项目仍把用例作为得到对象模型的方法。
Jacobson的早期的OOSE/Objectory包括这样一个我们称之为健壮性分析的阶段。在健壮性分析中,用例描述被解释为粗略地分割一系列协作对象。在分析的过程中,Jacobson提出将对象进行分类,把它们分为接口对象,控制对象,和实体对象。
这个小又快的建模步骤产生令人惊奇的收益。它帮助人们写出正确的用例,较早地确认客户端/服务器端和MVC设计信息,很可能最重要的是快速的浏览所有用例能确认可重用的对象。同时也填补了需求分析和具体设计之间的空白。
不幸的是,由于某些原因,健壮性分析的一些符号(三个轻易画的符号),在转变的过程中只有部分保留在UML中。符号仍然存在,但被分离到一个称为对象过程扩展的文档当中,并且工具支持也缺少。我把健壮性分析作为一个整体部分描述用例(图变成了文本的完全检查)时,发现学生已经很快适应了这个对象。
Important Questions重要的问题
你可以把整个领域的面向对象的分析和设计减少到两个简单的问题: 首先,系统中的对象是什么?其次,需要的系统行为如何在对象中分配?
已经明确要建立的正确的对象集,并且你已经为一个系统分配了合适的类集,你的项目将会进展顺利。最难的工作恐怕是我们听起来觉得很很顺耳的“分配行为是不错的工作”这句话,这也是有经验的面向对象分析者的生存之本。
Drive the Static Model from the Dynamic Models从动态模型中分离出静态模型
无论你打算在哪个过程使用UML,从动态模型中分离出静态模型(类图)是不错的实践方式,从较高层次的用例图开始,尤其是使用UML 时序图在类图中分配行为。 这个理论,是从Jacobson的OOSE/Objectory 过程中得来的,是1993年的时候一个关系好的Objectory咨询者解释给我听的。在过去的四年中我继续把它作为一种设计形式在教,它内在的聪明和广泛的应用让我已经越来越信服它了。
这个观点的本质在于: 通过遵从对象模型方法我们可以开始并且得到一个系统的粗略的对象集,这同通过问题描述来寻找名词得到“现实世界”或“问题领域”很相似。有时,我们可以做出聪明的猜测,一个非凡的类可能会是一个非凡操作的容器。但是,通常在面向对象的设计过程中,我们发现缺少用例开发来考虑静态模型是幼稚的。
以我的经验,面向对象分析与设计的实质在于真正好的方法解决类中分配行为的问题,把用例在更具体的(信息传递/方法)阶段。正规的或者非正规的,我所碰到的年长的的面向对象分析者大部分是这样设计的。当方法不正式时(不可见),设计者对怎样从一系列给定的领域对象和用例中得到一个明确的方法布满迷惑。通常,在使用一个系列像“多态、封装接口“这样的行话时这样的疑虑又会产生。这样能限制项目组成员完成有用的设计评估,让水平高的程序员更灵活地根据情况完成任务。
然而,在我看来,在UML(参看“UML模型如何匹配“,关注UML, SR4 页,时序图例子)中使用时序图设计方法才能更好的完成。时序图通过左侧的早先的(需求阶段,用户手册视图)父用例文本描述,图中间的实际的具体的动态行为(每一个方法和触发事件)描述来实现的。在一页纸上描述看出具体设计和需求阶段用例描述需要快速的浏览需求,可以证实至少你的用例设计符合需求。简单的重复系统中所有用例,将会得到一个可跟踪的设计。
画时序图的过程中,在设计中要确认具体的操作并把它分给具体的对象。虽然画动态(时序)图实际上也是在创建静态类模型。时序图是教我们如何从抽象的世界中找到对象模型的。
Defer Assigning Operations to Classes操作迟些分配给类
在项目分析阶段不要过多的去关注将操作放进哪个类中。除了大部分显而易见的情况外(有时连这些也会出错),很可能规划错误。经验告诉我,做这些行为分配决定的时候最好仔细,随着动态模型的开发一次一个。
要把这种分离一直记住(分析:什么是对象?设计:行为如何分配?)会帮助项目组定义分析和设计的界限。我们最先的统一对象建模过程方法在最初的分析阶段使用了对象建模方法符号,在设计阶段使用了Booch符号。在分析的过程中对象建模方法被使用,更具体的设计阶段的模型使用Booch方法。在UML中,这些符号被融合成单一的,对象模型方法。随着分析和设计符号的模糊不清,项目组经常要分清分析和设计的界限在哪儿会很困难。
即使我在教跌代和递增过程, 在某些逻辑点上,需求和设计评估是必须的。假如我在评估一个分析模型,我并不会很在意类的操作(在大多数场合,假如没有我会很兴奋)。我在寻找一个好的域类集和可以理解的用例模型。而在设计评估时,所有的操作都需要考虑在内,在时序图中需求和设计必须可以跟踪。设计者必须能解释清楚为什么他会把一些操作放在特定的类中。
Simply SUCcessful简单既成功
在项目中使用UML,需要时刻记住的是保持简单,先写用户手册(一次一个用例),同时让项目组对过程有统一的熟悉。记住,UML是一种符号,而不是过程。我所见到的最成功的项目都采用用例驱动,迭代,递增方法的。假如能把过程细化并且让项目组把握技巧,UML项目已经离成功不远了。