3.3 用况
本节要讲述用况的含义、用况与参与者之间的关系、用况间的关系以及如何使用它们描述系统功能。
3.3.1 概念与表示法
一个用况(use case)是描述系统的一项功能的一组动作序列,这样的动作序列表示参与者与系统间的交互,系统执行该动作序列要为参与者产生结果。
把用况表示成一个包含用况名字的椭圆,见图34。
除了用图符表示用况外,对用况还要描述其活动序列。对用况的描述,可使用自然语言、活动图(见53节)和伪码,也可以使用用户自己定义的语言。无论用什么形式,所描述的动作序列都应该足够清晰,使得其他人员易于理解。书写动作序列时,应该反映出用况何时开始和结束,参与者何时与用况交互,交换什么内容,以及用况中的基本动作序列和可选动作序列等。
以超市销售管理系统为例,图35给出了实现系统收款功能的用况“收款”的描述。
上面的示例描述的是通常的收款情况,对于用信用卡付款和给予优惠等的描述可使用333节中讲述的用况之间的关系。
图35中,采用缩进文字的方式描述系统的行为,使得参与者与系统的行为容易区分。
还有一种常见的描述用况的方式,即区分用况的交互序列的基本流和可选流。例如,在一个图书馆借书系统中,有一个用况为“确认图书证”。其基本动作序列(基本流)为:工作人员可以用扫描仪识别借书证,也可以用键盘输入借书证信息;随后系统检查输入的数据是否合法;如果合法,系统显示该客户的借书情况。可选的动作序列(可选流)有多个:例如,1)如果输入的数据不合法,系统就要求重新输入;2)如果该用户借书过多,则停止他再借书。
有的做法是把基本动作序列和可选的动作序列分开来写。下面以ATM 系统为例,采用基本流和可选流的方式,给出实现验证用户功能的用况“验证用户”的描述,见图36。
验证用户
基本流:系统提示顾客输入密码,顾客按键输入密码。顾客按“确认”按钮进行登录。系统确认是否有效。如果有效,系统承认这次登录,该用况结束。
可选流:顾客可以在按“确认”按钮之前的任何时刻清除密码,重新输入新密码。
可选流:如果顾客输入了一个无效的密码,用况重新开始。如果连续3 次无效,系统将取消整个登录事务,并在60 秒内阻止该顾客与ATM 进行交易。
在运用用况时要注意以下几点:
1)用况是一种类型,它是要被实例化执行的。当参与者实例使用由一个用况描述的一项系统功能时,该用况所描述的功能的全部或部分才发挥作用,其中经历的动作序列是该用况的一个实例,即一个场景(scenario)。
2)用况描述中的一个动作应该描述参与者或系统要完成的一个交互步骤。
3)执行用况的一个动作序列要为参与者产生可观察的结果,是指系统对参与者的动作要做出响应。例如,参与者向系统发一个命令,要求它做某件事;系统经过判断,要求参与者提供进一步的信息;参与者输入信息;系统进行处理,把结果报告给参与者。
4)用况描述的是参与者所使用的一项系统功能,该项功能应该相对完整,即应该保证用况是某一项功能的完整说明,而不能只是其中的一个片段。这就要求一个用况描述的功能,既不能过大以至于包含过多的内容,也不能过小以至于仅包含完成一项功能的几个小步骤。特别是,不能因为用况的功能过大,就像结构化分析方法把大的加工细分成下层的若干较小的加工那样,把用况也细分成下层的若干较小的用况,因为用况是不分层的,不能说上层的用况是由下层的较小用况组成的。
5)对用况的描述只强调用用况描述参与者和系统彼此为对方直接地做了些什么事,不描述怎么做,也不描述间接地做了些什么。例如,对于一个成绩管理系统的“成绩统计”功能,可以在某个用况中做这样的描述:“指定专业和年级,计算每个学生的各科成绩,并以成绩的高低为序打印成绩表。”该功能包含很多计算细节,如要进行数据检索、计算和排序等,但是这些细节并不在用况中描述。实际上,定义用况是在捕获需求,此时分析员还没有完全了解系统,还不能确定应该设立哪些成分以及成分之间的行为依赖关系,他们只能从系统的最高层次(即最接近参与者的层次)来观察和描述系统功能。对于参与者也只描述它对系统的直接动作(例如“输入某某数据”),不描述为了完成这个动作所进行的准备工作(例如为获得输入数据进行的调查、统计和计算)。
6)使用用况来可视化、详述、构造和文档化所希望的系统行为。尽管用况中描述的行为是系统级的,但在用况内所描述的交互中的动作应该是详细的,准则是对用况的理解不产生歧义即可。若描述得过于综合,则不易认识清楚系统的功能。
7)在用况描述中,由参与者首先发起交互的可能性较大,但有些交互也可能是由系统首先发起的。例如,系统在发现某些异常情况时主动要求操作员干预,或者系统主动地向设备发出操作指令。对于这样的情况,参与者和系统之间的交互就是由系统首先发起的。
8)在描述一个用况时,要求用况应该描述出可能出现的各种情况,并进行概括,不要顾此失彼;描述应力求准确、清晰,但不要把双方的行为混在一起。
3.3.2 用况与参与者之间的关系
一个参与者可以使用系统的多项功能,系统的一项功能也可以供多个参与者使用。在用况图中,体现为一个参与者可以同多个用况交互,一个用况也可以同多个参与者交互。对于前一种情况,参与者根据与其交互的各用况分别扮演了不同的角色。
在UML中,把参与者与用况间的这种交互关系称为关联。若没做具体的规定,交互是双向的,即参与者能够对系统进行请求,系统也能够要求参与者采取某些动作。
把参与者和用况之间的关联表示成参与者和用况之间的一条实线。若要明确地指出参与者和用况之间的通信是单向的,就在接收通信的那端的关联线上加一个箭头,用以指示方向。图37给出了一个参与者和用况之间的关联示例。
图37中的参与者“收款员”分别与用况“收款”和“检查商品”间存在着关联,参与者“统计员”与用况“收款”间存在着关联。这意味着“收款员”的实例与“收款”和“检查商品”的实例进行交互,“统计员”的实例与“收款”的实例进行交互。
3.3.3 用况之间的关系
不但在参与者和用况之间存在着关联关系,在用况之间也可存在一定的关系。例如,在下述情况下,就需要考虑产生新的用况,并在用况间建立关系:
在一个用况中存在着几处重复使用的动作序列。
在几个用况中存在着重复使用的动作序列。
一个用况中的主要动作序列或分支动作序列过于冗长或复杂,而且分离它们有助于对需求进行管理和理解。
UML把用况之间存在的关系分为三种:包含、扩展和继承。
1包含
在一个或几个用况中经常存在着重复的交互行为。为了避免重复,可把重复的交互行为放在一个用况中,原有的用况(基用况)再引入该用况(供应者用况),这样就在用况间建立了包含关系(include relationship)。原来用况中剩下的部分通常是不完整的,依赖于被包含部分才有意义,即供应者用况是包含它的基用况的功能的一部分。进一步地讲,从基用况到供应者用况的包含关系表明:基用况在它内部说明的某一(些)位置上显式地使用供应者用况的行为的结果。
可以把包含关系想象为基用况调用供应者用况(类似于子程序调用),基用况仅仅依赖供应者用况执行的结果,而不依赖供应者用况内部的结构。
建立包含关系的方法很简单,即从具有共同活动序列的几个用况中抽取出公共动作序列,或者在一个用况中抽取重复出现的公共动作序列,形成一个在几处都要使用的附加用况。这样,可以避免多次描述同一动作序列;当这个共同的序列发生变化时,这样做就显现出优势,即只需要在一个地方改动即可。
用一个敞开的带箭头的虚线(简称为虚箭线)表示用况之间的包含关系,该虚箭线从基用况指向被包含的用况(供应者用况),并在虚箭线上用include标记,见图38。
具有包含关系的用况间并不一定是一对一的。实际上,一个用况可以包含多个用况,一个用况也可以被多个用况包含,甚至一个供应者用况还可以包含其他用况。
2扩展
在一个或几个用况的描述中,有时存在着可选的描述交互行为的片段。在这种情况下,可以从用况中把可选的交互行为描述部分抽取出来,放在另一个用况(扩展用况)中,原来的用况(基用况)再用其进行扩展,以此来解决候选路径的复杂性。这样在描述基本动作序列的基用况和描述可选动作序列的扩展用况之间就建立了扩展关系(extend relationship)。进一步地讲,从基用况到扩展用况的扩展关系表明:按基用况中指定的扩展条件,把扩展用况的动作序列插入到由基用况中的扩展点定义的位置。
基用况是可单独存在的,但是在一定的条件下,它的行为可以被另一个用况的行为扩展。扩展用况定义一组行为增量,扩展用况定义的行为离开基用况可能是无意义的。注意,扩展用况中定义的各行为增量是可以单独插入到基用况中的,这与包括关系中的供应者用况要作为一个整体被包含是不同的。
用虚箭线表示用况之间的扩展关系。该箭头从扩展用况指向基用况(方向与包含关系相反),并用《extend》标记虚箭线,还可在《extend》附近写上扩展条件,见图39。
一个扩展点是用况中的一个位置,在这样的位置上,如果扩展条件为真,就要插入扩展用况中描述的全部动作序列或其中的一部分,并予以执行。执行完后,基用况继续执行扩展点下面的行为。如果扩展条件为假,扩展不会发生。
在一个用况中,各扩展点的名字是唯一的。可以把扩展点列在用况中的一个题头为“扩展点”的分栏中,并以一种适当的方式(通常采用普通的文本)给出扩展点的描述(作为基用况中的标号)。图310给出了一个示例。
在图310中,用况“使用ATM”有一个扩展点“选择”。当用况“使用ATM”的实例执行到达扩展点“选择”所标识的位置,且用户选择了帮助(即扩展条件{用户选择了帮助}为真)时,该用况就借助这个扩展点用用况“联机帮助”来扩展自己。图中的带虚线的折角矩形用于表示注释。
一个扩展用况可以扩展多个基用况,一个基用况也可以被多个用况扩展,甚至一个扩展用况自身也可以被其他扩展用况来扩展。
若要在基用况中表述可选的交互行为,就可以使用扩展关系。用这种方式把可选行为分离出来,通过扩展关系在扩展点使用它们。在对例外行为处理建模时或对系统的可配置的功能建模时,也可使用扩展关系。
3继承
用况之间的继承关系的含义如同类之间或参与者之间的继承关系一样。特殊用况不但继承一般用况的行为,还可以增加行为或覆盖一般用况的行为。一般用况和特殊用况均有具体的实例,特殊用况的实例可以出现在一般用况的实例出现的任何位置。
用一个指向一般用况的带有封闭的空心箭头的实线来表示用况之间的继承关系,见图311。
在本小节的最后要强调的是,尽管用况间的三种关系都有助于复用,但从上面的讲述中可以看出,它们之间是有区别的。
3.3.4 捕获用况
可以从如下几个方面来捕获用况。
1从参与者的角度捕获用况
用况用于描述参与者和系统之间的一系列交互。参与者用况通常是由参与者启动的,有时也需要在系统内部启动的用况。 通常作为交互的发起者,使用系统来完成某种任务。识别参与者的责任是寻找参与者与系统交互理由的良好基础。对所有的参与者,提出下列问题:
每个参与者的主要任务是什么?
是什么事件引发了任务,从而开始了参与者与系统进行交互?
在交互过程中,参与者是怎样使用系统的服务来完成它们的任务的?例如,参与者是否将读、写或删除系统的什么信息?参与者是否该把系统外部的变化通知给系统?参与者是否希望系统把内部的变化通知给自己?参与者是否希望系统把预料之外的变化通知自己?
参与者参加了什么本质上不同的交互过程?有些交互过程实际上是相同的或相似的,如果出现这些情况,需要合并用况或在用况间建立前述关系。
能完成特定功能的每一项活动明确地是一个用况。这些参与者参与的活动,通常会导致其他活动,进而可识别出其他用况。
2从系统功能的角度捕获用况
欲达到某种目的的一组动作序列要完成一项功能,这样的动作序列要描述在一个用况中。通常,以用况中的交互动作为线索能发现其他用况。如下是一些指导:
全面地认识和定义每一个用况,要点是以穷举的方式考虑每一个参与者与系统的交互情况,看看每个参与者要求系统提供什么功能,以及参与者的每一项输入信息将要求系统做出什么反应,进行什么处理。
以穷举的方式检查系统的功能需求是否能在各个用况中体现出来。
一个用况描述一项功能,但这项功能不能过大。例如,把一个企业管理信息系统粗略分为生产管理、供销管理、财务管理和人事管理等几大方面的功能,并分别把它们各作为一个用况,粒度就太大了。对于这种情况,应该把系统先划分成子系统(见141节),再针对子系统建立用况模型。
一个用况应该完成一项完整的任务,通常应该在一个相对短的时间段内完成。如果一个用况的各部分被分配在不同的时间段,尤其还被不同的参与者执行,最好还是将各部分作为单独的用况对待。
针对用况描述的基本流,要详尽地考虑各种其他的情况。
考虑对例外情况的处理。
3利用场景捕获用况
如果不能顺利地确定一个用况的描述,可尽早使用人们熟知的“角色扮演”技术。该技术要求建模人员深入到现场,通过观察业务人员的现场工作(就好像自己是业务人员一样),深入地理解业务人员的工作,将具体的工作流程记录下来,形成一个用来说明完成特定功能的动作序列,即一个场景。一个场景应该仅关注一次具体的业务活动,尽量要详细。要确定出谁是扮演者,他们做了什么事,他们做这些事的用意是什么,或者是什么原因要求他们做这些事。在描述一个场景时,还要指出其前驱和后继场景,并要考虑可能发生的错误以及对错误的处理措施。通过建模人员的角色扮演活动,找出各具体的场景;然后再把本质上相同的场景抽象为一个用况,如图312所示。
从另一个方面看,用况的一次执行也形成了一个场景。用况的一次执行所经历的动作序列可能为用况描述中的一部分。例如,在图35所示的例子中,若某顾客在一次购物中购买的商品只是一件,就不执行“输入商品数量”这个动作,也不需要多次执行for循环的循环体。
通过从上述三个方面捕获到的用况,有些是简单的,只有一个动作序列,有些要复杂一些,具有一些可选择的交互路径和多种例外的情况。一般而言,用况中含有一个在通常的情况下发生的基本动作序列,其余的为可选的动作序列。
3.3.5 用况模板
对于所捕获的用况,需要按一定的格式对其进行描述,形成用况规约。按照国家电子信息行业标准《面向对象的软件系统建模规范第三部分:文档编制》[14]的要求,图313给出了用于描述用况的模板。
在描述用况时,并不要求把用况模板中的每一项都写出来,而是可以根据需要进行相应的取舍。根据用况图,功能良好的建模工具能够把参与者以及包含、扩展和继承关系中的用况提取到用况规约中。