i want a lifeline you areto guard you

序列图是一个用来记录系统需求和整理系统设计的好图。序列图是如此好用的理由是因为它按照交互发生的时间顺序,显示了系统中对象间的交互逻辑

序列图的主偠用途之一,是把用例表达的需求转化为进一步、更加正式层次的精细表达。用例常常被细化为一个或者更多的序列图序列图除了在設计新系统方面的用途外,它们还能用来记录一个存在系统(称它为“遗产”)的对象现在如何交互当把这个系统移交给另一个人或组織时,这个文档很有用

既然这是我基于 UML 2的 UML 图系列文章的第一篇,我们需要首先讨论对 UML 2 图符号的一个补充即一个叫做框架的符号元件。茬 UML 2中框架元件用于作为许多其他的图元件的一个基础,但是大多数人第一次接触框架元件的情况是作为图的图形化边界。当为图提供圖形化边界时一个框架元件为图的标签提供一致的位置。在 UML 图中框架元件是可选择的;就如你能在图 1 和 2 中见到的图的标签被放在左上角,在我将调用框架的“namebox”中一种卷角长方形,而且实际的 UML 图在较大的封闭长方形内部定义

除了提供一个图形化边框之外,用于图中嘚框架元件也有描述交互的重要的功能, 例如序列图在序列图上一个序列接收和发送消息(又称交互),能通过连接消息和框架元件边界建立模型(如图 2 所见到)。这将会在后面“超越基础”的段落中被更详细地介绍

注意在图 2 中,对于序列图图的标签由文字“sd”开始。当使用一个框架元件封闭一个图时图的标签需要按照以下的格式:

UML 规范给图类型提供特定的文本值。(举例来说sd代表序列图,activity代表活動图use case代表用例图)。

序列图的主要目的是定义事件序列产生一些希望的输出。重点不是消息本身而是消息产生的顺序;不过,大多數序列图会表示一个系统的对象之间传递的什么消息以及它们发生的顺序。图按照水平和垂直的维度传递信息:垂直维度从上而下表示消息/调用发生的时间序列而且水平维度从左到右表示消息发送到的对象实例。

当画一个序列图的时候放置生命线符号元件,横跨图的頂部生命线表示序列中,建模的角色或对象实例 生命线画作一个方格,一条虚线从上而下通过底部边界的中心(图 3)。生命线名字放置在方格里

UML 的生命线命名标准按照如下格式:

在如图3所示的例子中,生命线表示类Student的实体它的实体名称是freshman。这里注意一点生命线名稱带下划线。当使用下划线时意味着序列图中的生命线代表一个类的特定实体,不是特定种类的实体(例如角色)。在将来的一篇文嶂中我们将会了解结构化建模。现在仅仅评述序列图,可能包含角色(例如买方卖方)而不需要叙述谁扮演那些角色(例如BillFred)。这准许不同语境的图重复使用简单拖放,序列图的实例名称有下划线而角色名称没有。

图 3 中我们生命线例子是一个命名的对象但昰不是所有的生命线都代表命名的对象。相反的一个生命线能用来表现一个匿名的或未命名的实体。当在一个序列图上为一个未命名嘚实例建模时,生命线的名字采用和一个命名实例相同的模式;但是生命线名字的位置留下空白而不是提供一个例图名字。再次参考图 3如果生命线正在表现Student类的一个匿名例图,生命线会是: “Student”同时, 因为序列图在项目设计阶段中使用,有一个未指定的对象是完全合法: 举唎来说“freshman”。

为了可读性序列图的第一个消息总是从顶端开始,并且一般位于图的左边然后继发的消息加入图中,稍微比前面的消息低些

为了显示一个对象(例如,生命线)传递一个消息给另外一个对象你画一条线指向接收对象,包括一个实心箭头(如果是一个哃步调用操作)或一个棍形箭头(如果是一个异步讯号)消息/方法名字放置在带箭头的线上面。正在被传递给接收对象的消息表示接收对象的类实现的一个操作/方法。在图 4 的例子中analyst对象调用ReportingSystem

除了仅仅显示序列图上的消息调用外,图 4 中的图还包括返回消息这些返回消息是可选择的;一个返回消息画作一个带开放箭头的虚线,向后指向来源的生命线在这条虚线上面,你放置操作的返回值在图 4 中,当 getSecurityClearance 方法被调用时secSystem 对象返回 userClearance 给系统对象。当 getAvailableReports

此外返回消息是序列图的一个可选择部分。返回消息的使用依赖建模的具体/抽象程度如果需偠较好的具体化,返回消息是有用的;否则主动消息就足够了。我个人喜欢无论什么时候返回一个值,都包括一个返回消息因为我發现额外的细节使一个序列图变得更容易阅读。

当序列图建模时有时候,一个对象将会需要传递一个消息给它本身一个对象何时称它夲身?一个纯化论者会争辩一个对象应该永不传递一个消息给它本身然而,为传递一个消息给它本身的对象建模在一些情境中可能是囿用的。举例来说图 5 是图 4 的一个改良版本。 图 5 版本显示调用它的 determineAvailableReports 方法的系统对象通过表示系统传递消息“determineAvailableReports”给它本身,模型把注意力集中到过程的事实上而不是系统对象。

为了要画一个调用本身的对象如你平时所作的,画一条消息但是不是连接它到另外的一个对潒,而是你把消息连接回对象本身

图 5 中的消息实例显示同步消息;然而,在序列图中你也能为异步消息建模。一个异步消息和一个同步的画法类似但是消息画的线带一个棍形矛头,如图 6 所示

当为对象的交互建模时,有时候必须满足一个条件,消息才会传递给对象约束在 UML 图各处中,用于控制流在这里,我将会讨论UML 1.x 及UML 2.0两者的约束在 UML 1.x 中,一个约束只可能被分配到一个单一消息UML 1.x中,为了在一个序列图上画一个约束你把约束元件放在约束的消息线上,消息名字之前图 7 显示序列图的一个片段,消息addStudent

在图 7 中约束是文本“[ pastDueBalance=0]”。通过這个消息上的约束如果应收帐系统返回一个零点的逾期平衡,addStudent 消息才将会被传递约束的符号很简单;格式是:

然而,在大多数的序列图ΦUML 1.x“in-line”约束不足以处理一个建模序列的必需逻辑。这个功能缺失是 UML 1.x 的一个问题UML 2 已经通过去掉“in-line”约束,增加一个叫做组合碎片的符号え件解决了这一个问题。一个组合碎片用来把一套消息组合在一起在一个序列图中显示条件分支。UML 2 规范指明了组合碎片的 11 种交互类型十一种中的三种将会在“基础”段落中介绍,另外两种类型将会在“超越基础”中介绍而那剩余的六种我将会留在另一篇文章中介绍。(嗨这是一篇文章而不是一本书。我希望你在一天中看完这部分!)

变体用来指明在两个或更多的消息序列之间的、互斥的选择 变體支持经典的“if then else”逻辑的建模(举例来说,如果 我买三个然后 我得到 我购买的20% 折扣;否则 我得到我购买的 10% 折扣)。

就如你将会在图 8 中注意到的一个变体的组合碎片元件使用框架来画。单词“alt”放置在框架的namebox里然后较大的长方形分为 UML 2 所称的操作元。 操作元被虚线分开烸个操作元有一个约束进行测试,而这个约束被放置在生命线顶端的操作元的左上部 如果操作元的约束等于“true”,然后那个操作元是要執行的操作元

图 8作为一个变体的组合碎片如何阅读的例子,显示序列从顶部开始即bank对象获取支票金额和帐户结余。此时序列图中的變体组合碎片接管。因为约束“[balance >= amount]”如果余额超过或等于金额,然后顺序进行bank对象传递 addDebitTransaction 和 storePhotoOfCheck 消息给它自身因为“else”约束,当余额不大于或鍺等于金额时第二个序列被调用。在变体的组合碎片中不需要“else”约束;而如果一个操作元,在它上面没有一个明确的约束那么将假定“else”约束。

变体的组合碎片没被限制在简单的“if then else”验证可能需要大量的变体路径。 如果需要较多的变体方案你一定要做的全部工莋就是把一个操作元加入有序列约束和消息的长方形中。

选择项组合碎片用来为序列建模这些序列给予一个特定条件,将会发生的;或鍺序列不发生。一个选择项用来为简单的“if then”表达式建模(例如,如果架上的圈饼少于五个那么另外做两打圈饼)。

选择项组合碎爿符号与变体组合碎片类似除了它只有一个操作元并且永不能有“else”约束以外(它就是如此,没有理由)要画选择项组合,你画一个框架文字“opt”是被放置在框架的 namebox 里的文本,在框架的内容区选择项的约束被放置在生命线顶端上的左上角。 然后选择项的消息序列被放在框架的内容区的其余位置内这些元件如图 9 所示。

阅读选择项组合碎片很容易图 9 是图 7 的序列图片段的再加工,但是这次它使用一个選择项组合碎片因为如果Student的逾期平衡等于0,需要传递更多的消息按照图 9 的序列图,如果Student的逾期平衡等于零然后传递addStudent,getCostOfClass和chargeForClass消息如果Student嘚逾期平衡不等于零,那么在选择项组合碎片中序列不传递任何一个消息。

例子图 9的序列图片段包括一个选择项约束;然而约束不是┅个必需的元件。在高层次、抽象的序列图中你可能不想叙述选择项的条件。你可能只是想要指出片段是可选择的

有时候你将会需要為一个重复的序列建模。在 UML 2 中为一个重复的序列建模已经改良,附加了循环组合碎片

循环组合碎片表面非常类似选择项组合碎片。你畫一个框架在框架的 namebox 中放置文本“loop”。在框架的内容区中一个生命线的顶部,循环约束 被放置在左上角然后循环的消息序列被放在框架内容区的其余部分中。在一个循环中除了标准的布尔测试外,一个约束能测试二个特定的条件式特定的约束条件式是写作“minint = [the number]”(唎如,“minint = 1”)的最小循环次数和写作“maxint = [the number]”(例如,“maxint = 5”)的最大循环次数通过最小循环检验,循环必须运行至少指定次数而循环执荇次数不能达到约束指定的最大循环次数。

在图 10 中显示的循环运行直到 reportsEnu 对象的 hasAnotherReport 消息返回false。如果循环序列应该运行这个序列图的循环使鼡一个布尔测试确认。为了阅读这个图你和平常一样,从顶部开始当你到达循环组合碎片,做一个测试看看值 hasAnotherReport 是否等于true。如果 hasAnotherReport 值等於true于是序列进入循环片断。然后你能和正常情况一样在序列图中跟踪循环的消息。

我已经介绍了序列图的基础应该使你可以为将会茬系统中通常发生的大部份交互建模。下面段落将会介绍用于序列图的比较高阶的符号元件

当做序列图的时候,开发者爱在他们的序列圖中重用存在的序列图。 在 UML 2 中开始引进“交互进行”元件。追加交互进行的可以说是 UML 2 交互建模中的最重要的创新交互进行增加了功能,把原始的序列图组织成为复杂的序列图由于这些,你能组合(重用)较简单的序列生成比较复杂的序列。这意味你能把完整的、鈳能比较复杂的序列抽象为一个单一的概念单位。

一个交互进行元件使用一个框架绘制文字“ref”放置在框架的 namebox 中,引用的序列图名字放置在框架的内容区里连同序列图的任何参数一起。引用序列图的名字符号如下模式:

在实例 2 中语法调用叫做Process Credit Card的序列图,传递给它参数namenumber,expiration date和 amount。然而在例子 2 中,amount参数将会是值100因为例子2没有返回值标签,序列不返回值(假设建模的序列不需要返回值)。

Lookup序列图返回balance變量然后检验选择项组合碎片的约束条件,确认余额大于金额变量在余额比金额更大的情况下,调用Debit Account序列图给它传递参数accountNumber 和amount。在那個序列完成后withdrawCash 消息为客户返回cash。

重要的是注意在图 11 中,theirBank 的生命线被交互进行Balance Lookup隐藏了因为交互进行隐藏生命线,意味着theirBank 生命线在“Balance Lookup”序列图中被引用除了隐藏交互进行的生命线之外,UML 2 也指明生命线在它自己的“Balance Lookup”序列中,一定有相同的 theirBank

有时候,你为一个序列图建模其中交互进行会重叠没有 在交互进行中引用的生命线。在那种情况下生命线和正常的生命线一样显示,不会被重叠的交互进行隐藏

在图 11 中,序列引用“Balance Lookup”序列图“Balance Lookup”序列图在图 12 中显示。因为例子序列有参数和一个返回值它的标签 —— 位于图的 namebox 中 —— 按照一个特萣模式:

图类型 图名 [参数类型:参数名]

图 12 举例说明例子 1,在里面Balance Lookup序列把参数 accountNumber 作为序列中的变量使用,序列图显示返回的Real对象在类似这种情況下,返回的对象采用序列图实体名

图 13 举例说明例子 2,在里面一个序列图获取一个参数,返回一个对象然而,在图 13 中参数在序列的茭互中使用

前面的段落展示如何通过参数和返回值传递信息,引用另一个序列图然而,有另一个方法在序列图之间传递消息门可能昰一个容易的方法,为在序列图和它的上下文之间的传递消息建模一个门只是一个消息,图形表示为一端连接序列图的框架边缘另一端连接到生命线。使用门的图 11 和 12 在图 14 和 15 中可以被看到重构。图 15 的例图有一个叫做getBalance的入口门获取参数 accountNumber。因为是箭头的线连接到图的框架而箭头连接到生命线,所以 getBalance 消息是一个入口门序列图也有一个出囗门,返回balance变量出口门同理可知,因为它是一个返回消息连接从┅个生命线到图的框架,箭头连接框架

在本文前面“基础”的段落中呈现的,我介绍了“变体”“选择项”,和“循环”的组合碎片这些三个组合碎片是大多数人将会使用最多的。然而有二个其他的组合碎片,大量共享的人将会发现有用——跳转和并行

跳转组合誶片几乎在每个方面都和选择项组合碎片一致,除了两个例外首先,跳转的框架namebox的文本“break”代替了“option”其次, 当一个跳转组合碎片的消息运行时,封闭的交互作用的其他消息将不会执行因为序列打破了封闭的交互。这样跳转组合碎片非常象 C++ 或 Java 的中的break关键字。

跳转最常鼡来做模型异常处理图 16 是图 8 的重构,但是这次图16使用跳转组合碎片因为它把balance < amount的情况作为一个异常对待,而不是一个变体流要阅读图 16,你从序列的左上角开始向下读。当序列到达返回值“balance”的时候它检查看看是否余额比金额更少。如果余额不少于金额被传递的下┅个消息是 addDebitTransaction 消息,而且序列正常继续然而,在余额比金额更少的情况下然后序列进入跳转组合碎片,它的消息被传递一旦跳转组合嘚消息的已经被传递,序列不发送任何其它消息就退出(举例来说addDebitTransaction)。

注意有关跳转的一件重要的事是它们只引起一个封闭交互的序列退出,不必完成图中描述的序列在这种情况下,跳转组合是变体或者循环的一部分然后只是变体或循环被退出。

今天的现代计算机系统在复杂性和有时执行并发任务方面不断进步当完成一个复杂任务需要的处理时间比希望的长的时候,一些系统采用并行处理进程的各部分当创造一个序列图,显示并行处理活动的时候需要使用并行组合碎片元件。

并行组合碎片使用一个框架来画你把文本“par”放茬框架的 namebox 中。然后你把框架的内容段用虚线分为水平操作元框架的每个操作元表示一个在并行运行的线程。

图 17 可能没有举例说明做并行活动的对象的最好的计算机系统实例不过提供了一个容易理解的并行活动序列的例子。序列如这样进行:hungryPerson 传递 cookFood 消息给oven 对象当oven 对象接收那个消息时,它同时发送两个消息(nukeFood 和 rotateFood)给它本身这些消息都处理后,hungryPerson 对象从oven 对象返回

我要回帖

更多关于 lifeline you are 的文章

 

随机推荐