用例图
结构化分析(SA)方法采用功能分解的方式来描述系统功能,在这种表达方式中,系统功能被分解到各个功能模块中,通过描述细分的系统模块的功能来达到描述整个系统功能的目的。采用SA方法来描述系统需求,很容易混淆需求和设计的界限,这样的描述实际上已经包含了部分的设计在内。因此,系统分析师常常感到迷惑,不知道系统需求应该详细到何种程度。一个极端的做法就是将需求详细到概要设计,因为这样的需求描述既包含了外部需求也包含了内部设计。SA方法的另一个缺点是分割了各项系统功能的应用环境,从各项功能项入手,很难了解到这些功能项如何相互关联来实现一个完整的系统服务的。
从用户的角度来看,他们并不想了解系统的内部结构和设计,他们所关心的是系统所能提供的服务,这就是用例方法的基本思想。用例方法是一种需求合成技术,采用各种需求获取方法获取用户需求,记录下来,然后从这些零散的要求和期望中进行整理与提炼,从而建立用例模型。在OOA方法中,构建用例模型一般需要经历四个阶段,分别是识别参与者、合并需求获得用例、细化用例描述和调整用例模型,其中前三个阶段是必需的。
1.用例图的元素
用例是一种描述系统需求的方法,使用用例的方法来描述系统需求的过程就是用例建模。在用例图中,主要包括参与者、用例和通信关联三种元素,如图2-1所示
(1)参与者。参与者(角色、动作者、执行者)是指存在于系统外部并与系统进行交互的任何事物,既可以是使用系统的用户,也可以是其他外部系统和设备等外部实体。
(2)用例。用例是在系统中执行的一系列动作,这些动作将生成特定参与者可见的价值结果。也就是说,用例表示系统所提供的服务,它定义了系统是如何被参与者所使用的,它描述的是参与者为了使用系统所提供的某一完整功能而与系统之间发生的一段对话。
(3)通信关联。通信关联表示的是参与者和用例之间的关系,或用例与用例之间的关系。箭头表示在这一关系中哪一方是对话的主动发起者,箭头所指方是对话的被动接受者,箭尾所指方是对话的主动发起者。如果不想强调对话中的主动与被动关系,可以使用不带箭头的关联实线。在用例模型中,信息流不是由通信关联来表示的,信息流是默认存在的,并且是双向的,它与箭头所指的方向没有关系。
2.识别参与者
参与者是与系统交互的所有事物,该角色不仅可以由人承担,还可以是其他系统和硬件设备,甚至是系统时钟。
(1)其他系统:当系统需要与其他系统交互时,其他系统就是一个参与者。例如,对某企业的在线教育平台系统而言,该企业的OA(办公自动化)系统就是一个参与者。
(2)硬件设备:如果系统需要与硬件设备交互,硬件设备就是一个参与者。例如,在开发
IC(Integrated Circuit,集成电路)卡门禁系统时,IC卡读写器就是一个参与者。
(3)时钟:当系统需要定时触发时,时钟就是一个参与者。例如,开发在线测试系统中的“定时交卷”功能时,就需要引入时钟作为参与者。要注意的是,参与者一定在系统之外,不是系统的一部分。可以通过下列问题来帮助系统分析师发现系统的参与者:谁使用这个系统?谁安装这个系统?谁启动这个系统?谁维护这个系统?谁关闭这个系统?哪些(其他的)系统使用这个系统?谁从这个系统获取信息?谁为这个系统提供信息?是否有事情自动在预计的时间发生?执行系统某项功能的参与者可能有多个,但这多个参与者在使用系统时会有不同的职责划分,根据职责的重要程度不同,有主要参与者和次要参与者之分。主要参与者是从系统中直接获得可度量价值的参与者,次要参与者的需求驱动了用例所表示的行为或功能,在用例中起支持作用,帮助主要参与者完成他们的工作,次要参与者不能脱离主要参与者而存在。开发用例的重点是要找到主要参与者。
3.合并需求获得用例
将参与者都找到之后,接下来就是仔细地检查参与者,为每一个参与者确定用例。首先,要将获取到的需求分配给与其相关的参与者,以便可以针对每个参与者进行工作,而无遗漏;其次,进行合并操作。在合并之前,要明确为什么要合并,知道了合并的目的,才可能选择正确的合并操作。合并后,将产生用例。将识别到的参与者和合并生成的用例,通过用例图的形式整理出来,以获得用例模型的框架,如图2-2所示。
在确定用例的过程中,需要注意以下问题:
(1)用例命名。用例的命名应该注意采用“动词(短语)+名词(短语)”的形式,例如,“开通课程”和“课程测试”等。而且,好能够对用例进行编号,这也是实现需求跟踪管理的重要技巧,通过编号可以将用户的需求落实到特定的用例中去。
(2)不能混淆用例和用例所包含的步骤。例如,“开通课程”功能要经过验证学员信息、检查学员权限、保存开通记录、修改课程选修人数等步骤才能完成,在系统中这些步骤不能作为单独的功能对外提供,它们只是一个用例所包含的事件流,或是用例的子功能。
(3)注意区分业务用例和系统用例。当针对整个业务领域建模时,需要使用业务用例,其中会涉及大量的人工活动,例如,在线教育平台系统中有一项重要工作是“编写教材”,这就是业务用例,是信息系统无法完成的。信息系统作为整个业务系统的一部分,只负责实现系统的部分功能,因此,只需要识别出系统用例,而不需考虑业务用例。
4.细化用例描述
用例建模的主要工作是书写用例规约(use case specification),而不是画图。用例模板为一个给定项目的所有人员定义了用例规约的结果,其内容至少包括用例名、参与者、目标、前置条件、事件流(基本事件流和扩展事件流)和后置条件等,其他的还可以包括非功能需求和用例优先级等。一个较为复杂的系统会有较多的用例,为便于理解,可以为它们建立多张用例图。更为复杂的情况将导致所有用例难以维持一种平面结构,这时可以对用例进行分组。UML使用用例主题划分用例图,一组用例放置在以主题命名的方框中(类似于系统边界),每个主题中可以包含多个用例图。用例的描述可以迭代完成,先对一些重要的用例编制相对细致的用例描述,对于一些不重要的用例,可以留待以后再补充完成。
用例描述通常包括以下几个部分:
(1)用例名称。用例名称应该与用例图相符,并写上其相应的编号。
(2)简要说明。对用例为参与者所传递的价值结果进行描述,应注意语言简要,使用用户能够
阅读的自然语言。
(3)事件流。事件流是指当参与者和系统试图达到一个目标时所发生的一系列活动,也就是用例所完成的工作步骤。在编写时应注意使用简单的语法,主语明确,语义易于理解;明确写出“谁控制球”,也就是在事件流描述中,让读者直观地了解是参与者在控制还是系统在控制;从俯视的角度来编写,指出参与者的动作,以及系统的响应;描述用户意图和系统职责,而不叙述具体的行为和技术细节,特别是有关用户界面的细节。执行一个用例的事件流有多种可能的路线,其中主事件流(基本事件流)是指能够满足目标的典型的成功路径,主事件流通常不包括任何条件和分支,符合大多数人的期望,从而更容易理解和扩展;备选事件流(扩展事件流)也称为备选路径,是完成用例可能出现失败的情况、分支路径或扩展路径,为了不影响用例活动清晰的主线,将这些分支处理全部抽取出来作为备选事件流。例如,在“开通课程”用例执行的过程中,如果学员所交的费用多于所选修课程规定的费用,则需要把多余的费用转换为学习币;如果学员选修课程数量超出大限额,则用例未达到期望目标而终止。在事件流的描述中,主事件流使用“确认”和“验证”等确定性语句,而不是“检查是否……”和“如果……,那么…….,否则……”等条件语句,这些分支情况利用备选事件流来说明。另外,事件流的编写过程也是可以分阶段迭代进行的,对于优先级高的用例花更多的时间,更加的细化;对优先级低的用例可以先简略地将主事件流描述清楚,备选事件流留待以后处理。对于一些事件流较为复杂的,可以在用例描述中引用顺序图、状态图和通信图等手段进行描述。
(4)非功能需求。因为用例所涉及的非功能需求通常很难在事件流中进行表达,因此单列为一
小节进行描述。在非功能需求的描述方面,一定要注意使其可度量和可验证。否则,就容易流于形
式,形同摆设。
(5)前置条件和后置条件。前置条件是执行用例之前必须存在的系统状态,如果前置条件不满足,则用例无法启动。例如,“开通课程”用例的前置条件是客服人员已正确登录到系统中;后置条件是用例执行完毕系统可能处于的一组状态。一旦用例成功执行,可能会导致系统内部某些状态的变化,例如,成功地“开通课程”会使该课程的选修人数增加,会使学员的权限发生变化等。而某些用例也可能没有前置条件或后置条件,例如,“学员联络”用例没有后置条件,因为该用例执行后不会改变系统状态。如果在当前阶段不容易确定前置条件或后置条件,则可以在以后再细化。
(6)扩展点。如果包括扩展(或包含)用例,则写出扩展(或包含)用例名,并说明在什么情况下使用。
(7)优先级。说明用户对该用例的期望值,为以后的开发工作确定先后顺序。可以采用满意度/不满意度指标进行说明,例如,设置为1~5的数值。
表2-2是图2-2中“开通课程”的用例描述,这些内容不一定要一次完成。如果需要调整用例模型,则在调整用例模型之后,还可以修改和细化用例描述。
表2-2 用例描述示例
1.用例名称:
开通课程(UC02)
2.简要说明:
为用户开通学习课程的权限,将其标记为“学员”,同时修改所选修课程的选修人
数。
3.事件流:
3.1 主事件流
1)客服人员向系统发出“开通课程”请求。
2)系统要求客服人员选择开通课程的类型(软考、考研、专业课程、自学考试、
Java课程)。
3)客服人员做出选择后,系统显示相应界面,让客服人员输入信息,并自动根据权
限规则生成权限。
4)客服人员输入学员的相关信息,包括学员用户名、所交费用、交费时间、选修课
程名称。
5)系统确认学员所交费用和所选修课程的规定费用一致。
6)系统将所输入的信息存储建档,开通学员课程权限。
3.2 备选事件流
5a)如果学员所交费用少于所选修课程的规定费用,则显示所选修课程的规定费
用,并要求客服人员选择修改或取消输入。
5a1)客服人员选择取消输入,则结束用例,不做存储建档工作。
5a2)客服人员选择修改用户所交费用后,转到5)。
5b)如果学员所交费用多于所选修课程的规定费用,则显示多余的费用数量,并要
求客服人员选择是转换为学习币还是退还给学员。
5b1)客服人员选择转换为学习币,则把多余的费用转换为学习币,记入学员账户
中,转到5)。
5b2)客服人员选择退还给学员,转到5)。
5c)如果学员所选修的课程超出了系统规定的选修人数,则提示客服人员,结束用
例。
4.非功能需求
无特殊要求。
5.前置条件
客服人员登录在线教育平台系统。
6.后置条件
修改学员权限,修改课程选修人数。
7.扩展点
无。
8.优先级
高(满意度 5,不满意度5)。
5.调整用例模型
在建立了初步的用例模型后,还可以利用用例之间的关系来调整用例模型。用例之间的关系主
要有包含、扩展和泛化,利用这些关系,把一些公共的信息抽取出来,以便于复用,使得用例模型
更易于维护。
(1)包含关系。当可以从两个或两个以上的用例中提取公共行为时,应该使用包含关系来表示
它们。其中这个提取出来的公共用例称为抽象用例,而把原始用例称为基本用例或基础用例。例
如,图2-2中的“学习课程”和“课程测试”两个用例都需要检查学员的权限,为此,可以定义一个
抽象用例“检查权限”。用例“学习课程”和“课程测试”与用例“检查权限”之间的关系就是包
含关系,如图2-3所示。其中“<>”是包含关系的构造型,箭头指向抽象用例。
当多个用例需要使用同一段事件流时,抽象成为公共用例,可以避免在多个用例中重复地描述
这段事件流,也可以防止这段事件流在不同用例中的描述出现不一致。当需要修改这段公共的需求
时,也只要修改一个用例,避免同时修改多个用例而产生的不一致性和重复性工作。另外,当某个
用例的事件流过于复杂时,为了简化用例的描述,也可以将某一段事件流抽象成为一个被包含的用
例。
(2)扩展关系。如果一个用例明显地混合了两种或两种以上的不同场景,即根据情况可能发生
多种分支,则可以将这个用例分为一个基本用例和一个或多个扩展用例,这样使描述可能更加清
晰。例如,图2-2中的学员进行“课程测试”时,其测试的次数可能已超出系统规定的限额,这时就
需要学员“充入学习币”。用例“课程测试”和“充入学习币”之间的关系就是扩展关系,如图2-4
所示。其中“<>”是扩展关系的构造型,箭头指向基本用例
(3)泛化关系。当多个用例共同拥有一种类似的结构和行为的时候,可以将它们的共性抽象成
为父用例,其他的用例作为泛化关系中的子用例。在用例的泛化关系中,子用例是父用例的一种特
殊形式,子用例继承了父用例所有的结构、行为和关系。例如,图2-2中学员进行课程注册时,假设
既可以通过电话注册,也可以通过网上注册,则“注册课程”用例就是“电话注册”用例和“网上
注册”用例的泛化,如图2-5所示。其中三角箭头指向父用例。
从UML事物关系的本质上来看,包含关系和扩展关系都属于依赖关系。对包含关系而言,抽象
用例中的事件流是一定插入到基本用例中去的,并且插入点只有一个。扩展用例的事件流往往可以
抽象为基本用例的备选事件流,在扩展关系中,可以根据一定的条件来决定是否将扩展用例的事件
流插入到基本用例的事件流中,并且插入点可以有多个。在实际应用中,很少使用泛化关系,子用
例的特殊行为都可以作为父用例中的备选事件流而存在。
在实际工作中,系统分析师要谨慎选用这些关系。从上面的介绍可以看出,包含、扩展和泛化
关系都会增加用例的个数,从而增加用例模型的复杂度。另外,一般都是在用例模型完成之后才对
它进行调整,在用例模型建立之初不必急于抽象用例之间的关系。