在前三章中通过(问题域)建模和用例分析之后,在许多的UML书中可能接下来就要进行时序
图和协同图的绘制了。但是问题好像还没那么简单,因为这里有一条鸿沟还没有跨过去,正如下图
所示:
在我刚学开始学习 UML时,在拿到用例文本时要去画时序图总感觉有些别扭,不知如何才能将
文本中的意思完全用图的形式表达出来,总是感觉分析出来的文本中缺了一些很重要的东西, 而这
些被丢掉的对象最终可能会导致无法绘制时序图,但又找不出用例文本中到底还有什么东西被遗漏,
最终导致设计瘫痪。后来从网上搜索到的一些文章里发现了这种方法(robustness), 在看了半天之
后感觉找到了方向和窍门:)
而本文的所说的内容在Iconix方法中的位置如下图所示(红圈标记部分):
好了,说了这些题外话,那这到底是怎样一种方法呢?
健壮性分析即Robustness,是Ivar Jacobson早在1991就发明了的,它最开始是用于解决用例
需要哪些对象这个问题,并指出参与场景的对象相互之间如何交互。这种技术本身是一种应用于分析
阶段技术(不是设计阶段)。它不是UML的核心部分,只是"三人帮"在创建UML时“发现”了它,把它
作为Objectory特定过程的扩展, 即通过使用构造型(stereotyping,一种UML技术)加以实现。同
时因为它通常不会被文档保存,只是以草图形式呈现(本文为了记录和给大家一个清晰的示例,使用
Rose图将它记录下来),所以在许多的00及 UML书中被打入“冷宫”。但该方法有着“承上启下”的作
用, 好在ICONIX方法又再次将它从“冷宫”中抬了出来,让它再次找到用武之地:)
那么它到底能做什么呢? 请看下图:
现在引用书中的解释就是:
1.它帮助您确保用例文本的正确性,且没有指定不合理或不可能的行为 (基于要使用的一组对
象),从而提供了健康性检查。
2.帮助确保用例考虑了所有必需的分支流程,从而提供了完整性和正确性检查。
3.让您能够(持续)发现对象,因为在域建模期间可能会遗漏一些对象, 而这些对象在绘制时
序图时不易被发现,并且很可能正是它导致无法绘制时序图。
4.缩小分析和设计的鸿沟,从而最终完成初步设计(关于初步设计复核会在下一篇中介绍)。
另外,该方法使用下面三种构造型元素:
实体对象(entity object):
通常是来自域模型中的对象(也就是现实世界),它常对应于数据库表和文件,这些数据表
和文件中存储了执行用例所需的数据。有些实体对象是“临时”对象(如搜索结果),当用例
结束后将消失。
边界对象(boundary object):
参与者使用它来同系统交互,这通常包含窗口,屏幕,对话框和菜单。如果有GUI原型,
将会知道许多主要的边界对象是什么。
控制对象(control object):
将边界对象和实体对象关联起来(通常被称为控制器,因为它们通常不是真正的对象),
它包含了大部分应用逻辑,它们在用户和存储的数据之间架起一座桥梁。控制对象中包含经常
修改的业务规则和策略。这样修改只需要在这些对象中进行,而不会涉及到用户界面和数据库
模式。控制器偶尔 (20%的时间内)也会是设计中的“真正对象”,但大部分时间内,控制器只
是一个占位符,用于避免您遗漏用例要求的任何功能和系统行为。
图形表示如下:
在看到这里,熟悉MVC的朋友可能会产生一些想法,就是上述三种对象与model,view,control有
些相似,这的确是一种巧合,同时也说明了Ivar Jacobson的远见卓识,大师必定是大师呀!!!
对应上面所说的三种构造型元素,有下面四个交互规则如下:
1. 参与者只同边界对象交互。
2. 边界对象只能同控制器和参与者交互(本人感觉这条并不绝对)。
3. 实体对象只能同控制器交互。
4. 控制器可同边界对象,实体对象以及其他控制器交互,但不能同参与者交互。
还有书中给出关于如何记住上面四个规则的简便方式就是:
边界对象和实体对象都是名词,而控制器是动词。名词和名词之间不能交互,但动词之间可以。
上面的四个规则可用下面这个图来表示:
注意图中的箭头不同于时序图(时序图中箭头代表消息的传递),而是一种逻辑关系, 也可以
说是通信关联。如: 从边界对象指向控制对象的箭头表明前者命令后者执行,控制对象和实体对象
之间的双向箭头表明它们相互进行读写。
另外书中对用例进行健壮性分析的方法是:
仔细检查用例文本,每次一个句子,并绘制参与者,边界对象,实体对象和控制器以及图中不
同元素之间的关系。
好了,有了上面的介绍之后,按照书中提供的绘制方法进行一下实践, 先以“登陆系统”为例:)
首先就是把
登陆系统
这个用例的文本列出来,以便进行相应分析。
用户名称: 登陆系统
基本流程:
用户在网站首页点击登陆链接,系统显示后台登陆页面。用户在登陆表单中输入其姓名,密
码然后点击提交按钮。系统在确认该用户提交信息有效之后,初始用户相关信息。并返回首页。
分支流程:
如果用户没有提供姓名,系统将显示一条错误信息,来告之用户输入姓名。
如果用户提供的密码不正确,系统将显示一条错误信息, 要求用户输入正确密码。
通过用例文本我们不难找出了"网站首页", "后台登陆页面"这个边界对象,同时因为系统提供了
校验功能(即当未提供用户名或密码不正确的情况下), 因此这里加上“验证”这个控制对象。另外为了
把错误信息显示到界面上也需要“显示”这个标准的控制对象。到目前为止,还没有从文本中发现实体
对象,这是非常不正常的,通过检查文本发现,系统需要去查找用户信息列表,找出与之相应的用户
信息之后才能确定登陆用户的合法身份,并初始用户相关信息。因此,这里需要将用例文本进行的修
改,以使文本所描述的信息更加合理。同时也要加入“用户信息列表”,“用户信息”这两个实体对象以
及“初始化用户信息”这个控制对象。(注意这里使用“验证”, “显示”这样的命名方式主要是增加该控
制对象的通用性,因为在分析一定数量的用例之后您会发现,这样的对象使用会非常频繁)
考虑文章的篇幅以及用户需求,这个用例基本上先分析到此,下面是相应的健壮性图:
另外要强调一点的就是大家千万不要在健壮性图上花费过多的时间,一是因为避免出现分析崩溃
的局面,另外就是会使用这种分析丧失它应有的价值和意义。
有了上面的那壶酒垫底,相信下面这个用例的健壮性分析就不会那么费劲了。
用户名称: 发表文章
基本流程:
用户在发表文章页面中输入文章标题,所属分类(自定义或系统类型),文章内容,是否使用
摘要,是否发表(或放入草稿箱)等信息之后点击提交按钮,系统在确认该篇文章提交信息有效
之后,使用当前数据添加到文章列表中。
分支流程:
如果用户没有文章标题,系统将显示一条错误信息,告之用户输入文章标题。
如果用户提供文章内容,系统将显示一条错误信息, 要求用户输入文章内容。
如果用户采用摘要形式发布,但却没有录入摘要内容时,系统将显示一条错误信息, 要求用
户输入摘要内容。
如果用户在未完成当前文章内容时要跳转到其它页面,系统将显示一条警告信息,提示用户
所编辑的内容将会丢失。
如果用户提交的文章标题已在文章列表中存在,系统将告诉用户并建议用户使用其它的标题。
通过浏览用例文本找出一个边界对象就是“发表文章页面”, 以及“验证”,“显示”,“检索”,“创建”
文章这四个控制对象。
另外要指出的是关于显示文章分类(供用户选择)的问题,这里要通过检索文章分类列表来获取,
因此需要添加一个“文章分类列表”的实体对象。另外一个实体对象就是文章列表,相信大家也都也
经看到了。下面就把相应的健壮性图贴出来,以便大家将相应对象按图入座:)
接着要说的就是"浏览评论"用例了,它的用例文本如下:
用例名称:浏览评论
基本流程:
用户浏览“评论列表”,列表当中显示评论人,内容,日期,评论人IP,所评论文章标题等
内容,并在每条评论上显示相关评论删除按钮。
分支流程:
如果用户没有任何评论,系统显示“您的文章评论为0”信息。
如果用户单击页面上的删除按钮,系统将打开“删除评论页面”(调用"删除评论"用例)。
这里因为它过于简单,就先将其健壮性图放出来,但如果大家细心阅读三种元素的交互规则的话,
会从中发现一个有争议的问题。
大家看到了吧,这里的边界对象“删除评论页面”和“删除评论按钮”直接交互了,但是前面说
过有关Robustness的元素交互规则如下:
边界对象只能同控制器和参与者交互。
其实这里的“删除评论页面”是在点击“删除评论按钮”之后才显示出来的,所在应该引入一个
新的“创建删除评论页面”控制对象会更合理,但熟悉软件开发的朋友应该都知道这只是一句话(web
开发中是一行js代码)就能搞定的事。所以就在这面省略了。其实这里再次告诉我们这样一个事实,
就是规则只是一些防止犯错误的条条框框,当开发小组已经能够有效避免相关错误时,相应的规则就
只是一种参考了,千万不要因为规则自身而约束了您的思维:)
然后再说一下“提交评论”用例
用例名称: 提交评论
基本流程:
用户点击浏览文章页面上的评论链接后,系统将链接重定向到评论页面。当用户输入评论内容,
用户名和校验码后,点击提交按钮,系统在验证用户身份后和校验码后,并将提交的评论信息添加
到评论列表中。同时显示提交成功信息后将页面重定向到浏览文章页面。
分支流程:
用户未输入用户名或评论内容,系统提示用户输入相应信息。
用户输入的校验码不正确,系统提示用户重新输入校验码。
系统发现当前用户名不是有效的系统用户,提示用户所用的名称不正确。
这里限于篇幅就直接将健壮性图放出来了,如果大家看着有什么问题可以在回复中进行讨论:)
最后要说的一个用例是“删除评论”
用例名称: 删除评论
基本流程:
用户在浏览评论列表上的相应评论上点击删除按钮。系统跳转到“删除评论页面”,在检索
到要删除的评论信息之后将该评论从"评论列表"中删除。同时将相应用户信息中的评论数减1。
并显示删除成功信息之后,将页面重定向到浏览评论页面。
分支流程:
当检索要删除的评论不在评论列表中(已被删除),系统将显示已删除该评论信息。
里面可以看到有两个边界对象,一个是"删除评论页面",“浏览评论页面”, 而控制器有检索,
删除,显示和更新(用户信息)。而相应的边界对象有“评论列表”,“用户信息”。将这些元素绘
制成Robustness图如下:
本人还绘制了其它一些用例的健壮图,但不是每个用例都有,这主要是因为写文章的时间紧造成的,
希望大家能够理解。如果感兴趣的朋友可以下载本章所提供的ROSE文件完成其余健壮性图的绘制工作。
这里不是要给大家布置什么homework, 只是希望大家能够通过实践来掌握这个工具,相信使用过它之
后,才能知道它的确很“厉害”。
还有要强调的是分析结束后不要忘记要根据分析结果更新一下域模型。如果不做这一步,等于半
途而废。这一点正如书中所说:“只有更新域模型后,健壮性分析才算完成,才能进入使用时序图的
交互建模阶段。毕竟,您无法将行为分配给那些没有出现在静态模型中的类”。
通过上面的几个用例的健壮性分析和已绘制的其它用例的健壮性图,将其中的关键属性分配到主
要的类中, 并对域模型做如下更新(见下图)
最后列出这个阶段最常见的健壮性分析错误及其相关说明(希望大家不要认为我在凑字,而是已有
朋友在前面三篇文章中怀疑其中一些常见错误的正确怀 为了便于说明相应错误的立足依据,所以在这
里引用书中的一些说明),以便给大家提供一个参考。有不同意见的朋友可以在回复中进行讨论:)
十种最常见的健壮性分析错误
10.违反一种或多种健壮性分析规则。
制定这些规则的主要目的是使文本格式为名词-动词-名词,并防止您在获得足够的做出设
计决策的信息之前将行为分配给对象。针对边界对象制定规则是为了确保您明确地指定边界对
象,用例涉及到的参与者位于这些边界对象的外面。
9.不使用健壮性分析来帮助您在用例文本中采用一致的格式。
模式边界对象-控制器-实体对象常出现在众多的健壮性图中。这种设计同英语句子中的主语
-谓语-宾语模式密切相关。应通过健壮性分析来确保用例文本的文体尽可能一致,这将极大地提
高它们的可读性和可维护性。
8.健壮性图中不包含分支流程。
应针对所有用例文本进行健壮性分析,而不仅仅是基本流程。系统大部分有趣行为都是在分
支流程中发生的,因此在建模工作中对这些行为进行分析至关重要。健壮性分析还将帮助您发现
新的分支流程,尤其是当您使用诸如“核对”和“验证”等标签绘制控制器时。
7.不使用健壮性分析来确保类图和用例文本中的类名一致。
在对象模型中指出系统使用情况是一个神奇的规则,要建立有用的时序图,必须使用这些规
则。通过在用例中对边界对象和实体对象进行命名,您已为时序图有一个良好的开端迈出了正确
的一步。对于每个用例您只需要简单地将这些对象放在时序图的顶端即可。
6.给健壮性图中的类分配行为。
控制器被用做功能和系统行为占位符。不应给健壮性图上的类分配方法,因为此时您很可能
还没有足够的信息。您将使用时序图来完成行为分配方面的决策。
5.包含的控制器过多或过少
建议每个健壮性图中包含 2-5个控制器。如果每个用例只有一个控制器,则很可能有大量非
常小的用例,其中每个用例没有描述足够多的行为。另一方面,如果一个健壮性图中包含10个以
上的控制器,则应考虑将用例分解成多个易于管理的用例。
4.试图使健壮性图十全十美,而花费过多的时间。
健壮性图相当于辅助引擎,它启动这样一个过程:即驱动用例向前发展,成为一个面向对象
的设计方案。健壮怀分析是一种工具,帮助我们发现对象,分配属性以及检查用例文本的完整性
和正确性。当我们完成整个任务后,就不再需要工具(健壮性图)了。这是一种实现目的手段,而
不是目的本身。
3.试图在健壮性图上完成详细设计。
临时性图的概念对初步设计很有用,但对详细设计没有任何用处。详细设计应在时序图中完
成。在健壮性分析中,应快速地检查要构建的所有场景,以给项目提供最大的价值。如果初步设
计的时间和详细设计的时间一样长,将失去这种快速的健康性检查的益处。
2.不在用例文本和健壮性图之间进行可视化跟踪。
建议您对照所有的用例文本和健壮性图进行复核,所有复核人员都采用手指跟踪方法。在没
有通过所有的可视化跟踪检查之前,用例就不能算完成。
1.不更新静态模型。
只有更新域模型后,健壮性分析才算完成,才能进入使用时序图的交互建模阶段。毕竟,您
无法将行为分配给那些没有出现在静态模型中的类。
ROSE文件(已复核过的用例和域模型)http://daizhj.cnblogs.com/Files/daizhj/blog_Sequrence.rar