用例方法
一,概述
用例技术是迄今为止最为深刻、准确和有效的系统功能需求(使用需求)描述/分析方法。在保障全球各类软件的成功开发中发挥了极其重要的作用。(技术性需求、业务规则和约束、UI需求等非功能性需求都不适合用用例来捕捉。)
UML的文档中,Use Case的定义是:在不展现一个系统或子系统内部结构的情况下,对系统或子系统的某个连贯的功能单元的定义和描述。
Use Cases本身是用户或其它系统与正在设计的系统的一个交互。这里我觉得要重点领会“功能”和“交互”这两个词。
用例就是各种系统受益人(Stakeholder,干系人)之间的行为(事件)序列(活动、动作和交互),从可观测性来看,就是多个在不同条件下执行并可能导致许多不同后续状态的情节(scenario,又译“场景”)的叠加,从价值目标来看,每个用例代表一个想要达到的用户目标。
而各种格式文本、UML图形(我们至少可以用4种UML动态图来描述用例)不过是用例的外部表现形式。所以,与其说亚克申博士发明了用例,还不如说亚克申博士早在20年前就发现了用例这种客观现实,并最终发明了用例表示和用例驱动软件过程的方法。
从软件系统来看,只要是软件,必然都存在用例:功能需求–价值目标;数据流,控制流,消息发送和数据交换–交互、活动/动作的执行以及状态的变迁。这些就是用例的本质(现象背后那个真实的、抽象的“胚”)
除了简单的小软件(用户少接口少功能简单)可以不必使用用例外,绝大部分的应用软件、系统软件都应该用例来做可测试、可验证的软件需求分析。如果分析只达到客户要求和软件特性这一层,往往导致大量需求风险乃至架构风险被隐藏到构造、移交阶段才暴发。
相关译法
use case用例(用况,使用的方式,用案,使用案例)
scenario情节(案况)
test case(测试用例,测例)
Actor使用者(参与者、执行者、主角)
User 用户
Supporting/Secondary Actor被使用者(辅使用者)
二,统一用例方法
目前用例技术尚存在几种相互竞争的流派,寇本用例方法以基于目标的结构化/半结构化文本描述见长,亚克申用例方法(RUP、UML及其支持者所采用的用例方法)更重视UML可视化建模和用例驱动过程。两者尽管同宗同源,细节差异却越来越明显。在实践中如何统一用例方法(UUCM,Unified Use Case Method),成为实践者必须面对的现实问题。
我们的较优策过渡略是采用统一的用例方法,是把亚克申和寇本用例两者结合起来,甚至融合其他的用例方法(据说多达18种以上)。
1,层次
寇本把用例划分为3个目标层次:A-概要层(目标摘要级别,+,用来包含多个B)、B-用户目标层(用户目标级别,!,真正意义上的用例)和C-子功能层(子功能等级,-,用来表达B的具体实现步骤),并通过引入巧妙的Why/How技术帮助分析者找到合适的目标层次,从而可以有效地把握用例的粒度(真正的用例最终应落实到用户目标层),防止用例情节的爆炸。
亚克申对用例的分解比较慎重,以避免用例倒退到结构化的功能分解,把寇本方法中的子功能层用例叫做用例片段以避免C与B名称上的混淆。
2,范围
用例本身是高聚合的,用例之间应该是低耦合,也就是说描述一个用例的时候要集中描述这个用例而非其它用例的功能,所以要把握设计的范围,保持每个用例粒度小,功能单一,清除范围外的功能设计。
用例可分为业务用例、系统用例两种
寇本强调在格式上用图标或文字显式地表示出每个用例的范围,并且在用例层次划分的基础上提出了最外层(或最外围)用例的概念。如同样一个用例名称,比如“取款”,可能实质上代表着两个截然不同的用例:一个是ATM取款(系统用例),另一个是银行柜台取款(业务用例)。所以在一个用例中明确标记出它的范围,是很有必要的。我们既可以用特定的图标,也可以用专门的格式字段来表明用例的范围,还可以对用例的名称加以修饰以便区分,比如“柜台取款”,“ATM取款”。
UUCM:用例的范围可以从需求分析(业务用例,包合了人)深入扩展到系统设计(系统用例,不涉及人),当然,系统用例往往是相应业务用例的一部分,在做项目需求分析时一般不予考虑。
4,包含与扩展/泛化
决定用例关系的不是表面名称,而是用例内容。用例之间的关系价值不大。总之,如果分不清,可以都先定为包含关系,这样做并不影响后续的系统分析设计和使用。
同样一对用例之间的关系,在寇本用例模型中是包含关系(关注目标完整执行),在亚克申模型中却可能被表示成扩展关系(不够抽象拔高,低效)
采用包含还是扩展关系判断:如果触发条件中含有基用例负责(知道该用例何时、何处、为什么发生)的事物,那么用包含;如果触发条件中含有附加用例负责的事物,那么应该用扩展。小经验:凡是在用例基本流中出现的附加用例都应作为包含用例,而在扩展流中出现的附加用例必然是扩展用例。
另外,UML 2.0采用了继承(泛化),此不展开。
另外,尽量不要采用寇本的包含用例定义sub use case(实指分用例,但一般会被误译成子用例,会和OO方法混淆),可以用“包含用例”或“附加用例”来代称,同时明确约定在中文中凡是提到“子用例”的地方,就是指用例的继承或一般化。(在UML中,把包含用例、扩展用例统称为附加(additional)用例,被包含、被扩展的用例叫做基用例,在用例的继承关系中则采用父用例、子用例的说法,这样做才是妥当的。)
5,Actor
UML及亚克申的Actor是系统之外的人或物,而寇本Actor的范围要大得多,有内外Actor之分。从划定系统(或业务)的边界的需要来看,内部Actor是不必要的概念。另外,寇本关于stakeholder的定义也不妥当。
6,后置条件
建议采纳寇本方法的最小保证(系统不管在任何情况下,尤其当用例失败、目标未达成时,都应满足的起码条件和应采取的措施。)和成功保证划分。此外,在前置、后置条件(最小保证和成功保证)中除了说明必须满足的条件外,还可以分别说明系统在用例开始前和结束后的状态,包括各种成功和失败状态以及对失败状态的处理。
7,动作步骤
建议采纳寇本的步骤编号方式(而不采用RUP的自然分节的顺序编号),基本流采用1,2,3…顺序编号,扩展流的条件和扩展步骤采用数字、字母间隔的方式,如1a、1a1、5c、5c3b1等等,而且还可以使用宏代符*,可以指定任意数目步骤的条件,如1-9a、2,7-9c等等,使用起来非常方便。
如果一个步骤内容较多,采用RUP的命名步骤方法,用一个短语标记来概括说明该步骤执行的大致内容,可作为用例活动图的快速参考。
8,文本与UML
结构化/半结构化的文本描述直接描述用例的本质内容。如果可以先写好文本系统用例,就可容易地照它来画UML图。当然,文字太繁琐而不直观,对于复杂和关键的用例,除了一些必要的文本描述之外,再辅之以UML(用例图、序列图、协作图、活动图和状态图)进行可视化,有助于迅速抓住问题本质要领。二者应结合使用。
9,黑盒白盒
建议使用亚克申博士的UC和用例实现(UCR,Use Case Realization),而不使用寇本的黑盒用例(透明黑盒,需求)和白盒用例(不透明白盒, 需求的实现,概念混淆)。严格地区分UC和UCR有助于项目团队在实践中消除需求和实现不分的情况,避免把需求分析写成了软件设计方案了。
10,格式模板
寇本在WEUC中一共列出了5种主要的用例格式模板:完整型、简易型、单列表式、双列表式和RUP样式。在此,我们推荐以完整型(寇本本人最喜欢的)为基础,结合了单列表式和RUP样式特点的UUCM模板。(参考WEUC)
双列表式较多地被用来描述用户界面需求,有些人偏爱它,但我们发现双列表不够简洁,比较占空间,而且很多情况并不适用,比如参与者多于两个的情况。
格式如下(可选的为根据实践另外补充的)
标识符 [可选]:唯一标识符,以便项目中引用该用例。 版本 [可选]: 日期/版本号/作者/简述 状态 [可选]:进行中/等待审查/通过审查/未通过审查。 频率 [可选]: 参与者使用该用例的频率 修改历史记录 [可选]:修改时间/原因/修改人 问题 [可选]:todo 开发相关的问题/操作项目列表。 决策 [可选]:SME关键决策(属于用例)的列表。
用例名称: 层次:+ | ! | - 范围: 简述/背景/说明: 主使用者(参与者)及利益: 其他受益人及利益:
受益人1:
受益人2: 前置条件: 条件1:
条件2:
状态1:
状态2: 后置条件: 触发事件: 最小保证: 状态1:
状态2: 成功保证:
基本流: 1. 步骤1
2. <可选名称>.步骤2 …
n. 步骤n <结束> 扩展流: 1a. 条件1:
1a1. 步骤1
1a2. 步骤2 扩展点: 名称1:位置1
名称2:位置2 技术和数据变化:
1a.
2a. 非功能需求: 业务规则: 备注: 其他必要字段 ……
三,文本用例写作要领:
1,用例名称:用短的动词词组说明这个用例会达成的目标。
2,层次:+ | ! | - 可用前面三个符号以及类似风筝/海平面/鱼的象形图标来标明 目标摘要(最外层用例,情景目标)/用户目标/子功能目标。
3,范围:使用 项目范围内/外 清单 来明确界定讨论的系统边界。然后用类似房屋/黑箱白箱/螺丝钉的象形图标来表示企业/系统/子系统范围。
4,参与者:使用穷举法来列出参与者/目标/优先级 清单
使用 参与者/用例概要 来发现有相关利益者和各参与者相应的最外层使用案例。
每个用例中的关系人名称与其利益。一般来说,我们应该可找到2到5 种关系人:主要参与者(用例名称一般体现其利益。通常是取得某样东西)、公司拥有者(确认利润,体现在主要参与者获得东西后必须付费)、可能会有的政府机构代表(确认公司遵守政府领导,体现在通常要保有某种系统纪录。),以及其它可能会有的人。或许负责测试或维护的员工也会对使用案例操作情形有利益存在。
5,触发事件:在用例中,主要成功情节会有触发事件;另一方面,扩充情节的扩充情况就是触发事件。写用例时,请从触发事件开始写,一直写到目标达成或放弃为止。
6,行文风格:
从目标等级最高的目标摘要用例开始,写出有一致性的叙事情节,使用者/子功能的用例从其中分流出来。当有条件判断的时候,表述上采用"系统检验到…",不要使用“如果”等字词。同时选择一个条件分支作为用例的主路径,其他的条件分支放在扩展事件流中。
简要易读。使用"现在式/主动语态/主动动词”的语法来描述参与者成功达成子目标推动过程前进一步的情景。(请在句子的前一两个字很快点出做动作的参与者名称。不能这样写:用户名和密码已输入。)
要把握好粒度,不要大到超出设计范围,也不要小到成为软件接口设计(一般是不必要写出GUI的),比如下面的话,有三种描述。
a.用户输入信息 b.用户输入用户名和密码 c.用户在编辑框输入用户名和密码 很显然b是最恰当的。
7,主要成功情节:一般有三到九个动作步骤,而且每个动作步骤的目标等级,基本来说都只比这个用例的目标等级低一点。如果你发现主要成功情节中有超过九个动作步骤的话,请找找看是否存以下合并可能:
a, 多个连续步骤中,都是同一个参与者在做不同动作
b,使用者接口动作:在某个步骤中,我们过分描述参与者动作到了设计接口的地步,而我们需要关注的是参与者的意图,而非动作。
c,在某些动作步骤中,两个参与者间有许多简单的来回动作。试着问自己这些来回动作是否要达成某个更高一级的目标?如果是,就能用这个目标合并好几个动作步骤。
8,子目标:用主动动词写出完整句子,里面描述欲达成的子目标。 请确定每个动作步骤中都有明确写出参与者与其意图。
9,失败情况:针对交易行为,系统有必要(最小保证)log记录,而失败情形的复原方式一般都牵涉到某方面关系人的利益,所以尤其需要log记录。失败情况描述要简明有序,使其复原动作变得很易读。但不要简略到"接下来会执行步骤3a2"的不易读的地步。
10,扩充情节:
可用不完整/完整的句子/过去式来写,结尾处用分号而不用句点。
把替代行为放在扩充情节中,请不要在用例的主要成功情节中用条件子句写出替代行为。
a,针对每个被呼叫到的使用案例,我们都要处理它的失败情况。
在扩充情节中,所有步骤最后都会回到MSS ,有可能是以成功传回、也有可能是以失败传回。
每个使用案例都会以两种方式结尾:成功或失败。当动作步骤呼叫某个子使用案例时,被呼叫的使用案例可能会以成功或失败结尾。如果我们是在主要成功情节中呼叫的,那么就要在某个扩充情节中处理这个失败情形。如果我们是在扩充情节中呼叫的,那么就要在同样的扩充情节中同时描述成功与失败处理方式。(可用条纹裤来作比喻)
b,我们必须确认使用案例有满足每个关系人的利益,特别是当目标失败时,我们必须保障关系人的利益。
11,事后保证/后置条件:记录用例是如何满足这些关系人利益的。在项目关键而紧急时最好在写主要成功情节之前先写出事后保证,以便团队随时做成败检验。
12,事先条件:用例的有效运作条件。是系统确认执行前会成立的东西。记录后就不必再重新检查。
最常见的事先条件是:使用者已登入系统,他的身分也被证实过了。 另一个经常会变成事先条件的情况是:第二个用例半路拦截第一个用例的执行活动,前者会认为第一个用例已设定好它可信赖的某些特定条件。例如假设使用者在第一个用例中已选好(部分)产品,这时候,第二个用例会在它的处理过程中用到已选好产品的相关知识。此时事先条件就成了更高目标等级的用例的存在标志,而且该用例设定了目前用例的事先条件。
13,扩充用例:就像基本用例的补丁。可以把扩充用例视为长得太大的扩充情节,因此需要有自己的独立空间。于其中写出基本用例名称、定出它中断基本用例时的情境。相反地,基本用例中则不会写出扩充用例名称。如果你希望有任何数量的用例可中断基本用例,却不会有每新增一个中断的用例,就更新基本用例一次的维护恶梦,那么扩充用案就是一种很有用的做法。
最常写出扩充用例的情况是:使用者想在许多地方中断基本用例、执行异步服务。通常,这些异步服务是由其它开发团队负责开发的,而且我们通常会在建构软件包的套件时这么做。
其它常见的情况则是在替锁定不变的需求文件新增功能时发生。在渐增式、分不同时期开发的项目中,你可能会在每个版本发行之后锁定需求,再用新增功能去扩充这个锁定不变的用例。
14,重新调整整组用例:必要时新增、粹取或合并一些用例。重新讨论并修正目标摘要等级的用例。我们可以新增、删除或合并一些目标。请再次检查一下位于系统边界、由时间所触发的事件或其它事件。把比较复杂的流程粹取成子用例(会增加用例的维护成本);不重要、比较小的子使用案例则合并回到呼叫它的用例中。
15,检查可读性、完整性,以及是否符合关系人的利益。
四,UML用例图绘制:
1,包含关系:从(目标等级比较高的)基本用例画虚线箭头到被包含用例上。替箭头加上「<<includes>>」造型(stereotype)。尽量把等级比较高的目标画得高一点,那么虚线箭头总是会往下画。
2,扩充关系:从扩充用例画虚线箭头到基本用例,替箭头加上「<<extends>>」造型,寇本还会画一个挂勾把扩充使用案例勾在基本使用案例上以示区别。把扩充使用案例的位置画得低一点。
3,泛化(一般化)关系:请务必把一般性的目标画得高一点,而且是由下而上画出三角中空箭头,而不要像包含关系或扩充关系一样从侧面画。
4,虽然UML没有规定箭头的特别用处。但对UML中的各种用例关系,请用不同的箭头形状,以易读,不会跟其它UML 符号产生混淆。
包含(includes)关系:请用预设的开放式箭头,因为它是最常用的一种箭头。
一般化(generalizes)关系:在UML 中,标准的一般化关系箭头是用三角中空箭头代表的,请用这种箭头。
扩充(extends)关系:请用一种跟包含关系、一般化关系完全不同的箭头形状。寇本用挂勾符号把扩充使用案例勾在基本使用案例上。
尤其在扩充点上,尽量不要在UML图中标注而分散注意力。可用文字来说明基本用例中哪个地方是扩充用例可扩充的。(当然,当我们在画UML 的图时,通常会根据不同需要,选择性地秀出模型元素(例如代表类别的方块)中的某个部分(例如类别中的方法)。)
5,单纯使用椭圆形与简单棒形人偶图标会导致UML图复杂不易读。不要把读者置于画满一层层箭头、像补鼠网的图中,却希望他们能理解你想表达的东西。
6,不要在情境图中画出目标等级比使用者目标等级更低的目标。如果你想用图来分解用例的话,请把分解后的结果另外放在其它页中。
7,把所有主要参与者放在代表系统的方块左边、剩下的支持性参与者(次要参与者)则放在右边会便于区别。
8,以文本用例(用例本质内容)为基础来理解UML图用例间关系
参考资料: 寇本《Writing Effective Use Cases》目前最详细的用例教材 亚克申《面向对象软件工程:用例驱动方法》《统一软件开发过程之路》《统一软件开发过程》 Use Case 方法综述 http://swordcane.meansys.com/blog/CommList.aspx?TempleCode=1000000024&BlogLogCode=1000060821 没头没尾–项目开发笔记:如何编写最外层用例?!http://blog.hexun.com/viktoryu/viewarticle.aspx?articleid=10628