2. 1 基于用例的系统行为建摸
系统的行为(即功能)是由用户提出的需求所决定的。现在,我们开始面对客户,倾听他们的讲述。关 于所要开发项 目的需求。这是一个生产计划系统 ( P rod uce Plan Sys tem ) 项目,简称它 为 PPS 项目。PPS 项目要解决的首要问题是如何根据订单量来保证原材料的最低库存量。根据用户的描述,可以初步确定 PPS 系统具有以下行为特征: 创建销售订单、取消订单、创建生产计划单、创建采购合同、取消采购合同、零配件出库 、零 配件入库、计算预计可用库存撮等。
我们需要对PPS 的需求进行细化,即 把一个大问题分解和抽象为若干个子问题。这些子问题就是用例( Use Case) ,它 描述的是系统行为,UML 正是用用例图为系统行为建模的。
2.2 用 例 图
用例图( Use CaseDiagram) 主要用于描述系统的行为及各种功能之间的关系,是描述参与者( Actor) 与用例以及用例与用例之间关系的图。用例图从用户和外部系统的角度,分析和考察系统的行为,并通过参与者与系统之间的交互关系描述系统对外提供的功能特性。 UML的用例图由参与者、用例及它们之间的关系组成, 它的表达方式为:

2.3 用例图的表示方法
2.3.1 参与者
参与者是用例的启动者,参与者处于用例的外部并且能够初始化一个用例,但它并不是所描述系统的一部分,它 可能是人或其他外界系统。
UML 表示参与者的方式有很多种,最常见的是用简笔人物画表示,将参与者的名字放在简笔人物画的下面,如图 2- 1 所示。
在 U M L 2. 0 中参 与者的符号被表示为图 2- 2 的形式。
图 2- 2 中的 < < A ct o r > >是 一 个 构造型( Stereotype ) ,表 示当前的UML 元素表达的是参与者的概念。在图 2- 2 中 ,pl anner 是参与者的名字,它通常是一个名词。
构造型可以扩展已存在元模型的语义,具体 可以参见附录 A


2.3.2 用例
Booch 等人 在 19 99 年 出版 的 Unif ied Modeling Language UserGuide 中将用例定义为“若干动作序列集合的描述,包括 由 系 统 执 行 并 产 生 可 观 察 的 、对某 参 与 者 有 价值的 结 果 的 变 体 ”, Rat i onal统一过程 (Rat ional UnifiedP rocess , RU P ) 将用例定义为“一系列包含变量的动作描述,系统 由 此 对 特 定 用 户 产生 有 价 值 的 可见结果”
用例技术简史
用例技术的创始人是 Ivar Jacobson。 1967年 ,Jacobson开始在爱立信公 司从 事对大量不同电话呼叫类型建模的工作。 当 时他把 各种不同 类型的电话呼叫情况称为Traffic Case。 1986年 春 天,在 研 究 如 何 把 Traffic Case 映 射 到 功 能 的 过 程 中, Jacobson突然产 生了灵 感,发明 了 UseCase这个术语。
在提 交 给 OOPS LA '86 的 一篇 会 议 论 文 La ng ua g e Support for Changeable Larg e Rea l TimeSystems. 中 ,Jo co bson 首次提 出了 用例的概念 ,可惜 当 时那篇文章没有被 OOPSLA 接 受。 1987 年 ,Jaco bson 在 论 文 Obbject-Oriented Development in an IndusrtiaL Envrionment中进一步介绍了许 多 用例建模的关键 思 想 ,并提 出用例是由用 户和 系统 在 一次对话中执行的一个特殊事务序列。 此后,用例的方法很 快被人们所接受,并大量应用 于需求工程中。
在荻得 了 深 入 理 论 研 究和充分实践 经验 的 基 础上,Jaco bson 与 其同 事 一起 于1992 年 出 版 了 0bject-Oor iented Softtwa re Engineeri ng: A Use Case Driven Approach ,奠定 了 OOSE 和用例方法的基础,这无疑是一本软件工程 史上划时代的里程碑之作。
1995年,Jacobson加 入了 Rational公 司,并与 另 两 位 大师 GradyBooch、James Rumbaugh携手一同领导 面向 对 象建模 语 言的统一进程,用例和 OOSE随之 融入了UML,并 与Objectory过 程、Rational方法结合产 生 了 如 今 闻名遐迩的 Rational统一过程( R UP )。 RUP 的 三 个基本特征 就是 用例 驱 动、以架构 为 中心 和 迭 代 递 增 式 开发 。
简单地说,用 例 就是对一组动作序列的描述,系统执行该 动作序列为系统 的参与者产生一个可观察的结果。这个动作序列就是业务工作流程。
用例反映用户的需求,而不是反映开发人员的愿望。
找到参与者之后,就可以根据参与者来确定系统的用例,主要通过考察系统的各个参与者需要系统提供什么样的服务,或者说参与者是如何使用系统的。
U ML 有两种表达用例的方式: 一 种是用一个椭圆加上一个放置在椭圆中心的用例名称来表达用例,创建销售订单的用例如图2- 3 所示。

另一种方式是用分栏的矩形框来表达用例,第一栏标明用例的名称,并 且 在右上角画一个小椭圆表示当前的 UM L 元素表示的是用例,矩形框的第二栏放置其他与这个用例有关的细节,例如扩展点 、被包含用例等。如图 2- 4 所示,在用例Create O rd er 中,增加 了 扩展点构造型 < < E xt e ns ion Poi nt > > 表示该用例有一个扩展点称为 sa le s t yl es 。

所有用例都应该有名称,建议使用动名词为用例命名。例如,用例 CreateOrder 或 EstimateAvailableInventory。 这反映出用例应始终以用户的角度来定义,而不是以系统功能的角度定义。
可以将一个参与者与一个或多个用例关联(Assoc ia tio n) ,这种关联关系揭示了参与者初始化一个用例,而用例向参与者提供有价值的可见结果。关联关系用实线来表 示,如 图 2-5 所示,用实线将参与者 sales man 与用例 C reat e Orde r 和 Ca ncel O rder 连接起来以表达这种关联关系。

一个系统中的每个功能都有它的所属范围,所以用例用系统边界( Sys t em Bou ndar y ) 来定义这种范 闱。在决定参与者、设计一个系统 、子系统或某个部件的时候,这种划分系统边界 的技术对千决定 系统的规 模和分配责任是十分有用的。
系统边界是用来表示正在建模系统的边界,边界内表示系统的组成部分,边界外 表示系统外部。
UM L 使用矩形框来表达系统 的边界,在矩形 框的左 上方放 置系统的名 字。
例如,如果所要定义的系统边界仅限于业务员的工作,那么 Cr ea te Order 和Cance l O rder 就应属于 Sale S ys te m ,如图 2- 6 所示。

比较库 存 Es t i ma te Ava i labl e I nvento ry、零配件 入库 S toc k In 和零配件出库Stoc k O ut 属于库存 系统 S torage Sys tem ,创建采购合同 C reate P urchase Co nt ract 和取消采 购合同 Ca nce l P urchas e Co ntract 则属于采购系统 P ur chas e Sys t e m。图 2- 7 和图 2- 8 列出了不同参与者的系统边界。
在 PPS项目中,通过需 求分析,识别出了参与者,它们包括: salesman、purchase r、storeman和 planner。我们 捕获了几个用例,当然 ,这只是 PPS项目的一部分用例,注意,用 动名词 为这些 被捕获的用例命名。图 2-9是 PPS项目用例图的最初版本(附录B中给出了 PPS项目中的部分用例的详细描述)。



2.3.3 用例之间的关系
在简单的用例图中,只 表述参与者和用例之间的关系。但有时需要表达参与者之间以及用例之间的关系。
可以认为用例之间都是并列的,它们并不存在着包含从属关系。但是从保证用例模型的可维护性和一致性的角度来看,用 例建模提供扩展( Extend),包 含( Include) 和泛化( Generalization) 关 系支持对不断增加的复杂性和细节进行细化,也 就 是 说 ,可以在用例之间抽象出包含、扩展和泛化这几种关系,从现有的用例中抽取出公共的那部分信息,然后通过不同的方法来 重用公共信息以减少模型维护的工作量。
1. 泛化关系
泛化关系是两个用例或两个参与者之间的关系。
当多个用例共同拥有一种类似的结构和行为的时候 ,可以将它们的共性抽象为父用例,其他 的 用 例 作 为 子用例,用例 间 的 这种关系被称为用例的泛化关系。A 是 B 的泛化 ,意 味着 A 描述的是一般的行为,而B是这些行为的详细( S pecific) 版本,A 被称为父用 例( Parent U se Cas e ) 或基用例(Base Use Case), B 被称为子用例( Chi ld Use Cas e) 。在用例的泛化关系中 ,子用例是父用例的一种特殊形式,子用例继承(I nh er i t ) 了父用例所有的结构、行为和关 系。
在用例图中,泛化关系用实线加上空心的箭头来表示。子用例被连接在箭头的尾部,箭头 指向父用例。以 PPS 项目为例,用 例 C r e ate Who l e s ale O rder 和Crea te RetailOrd er 都包括一系列公共的行为,如系统提供空白订货单表、业务员输入客户信息、业务员选择产品销售方式、业务员 填写需 求数扯、系统显示产品价格并且合计总价等,因此,可以将这些公共的行为泛化为用例 C rea te Order,如图 2-10 所示

参与者之间也 存在着这种泛化关 系。例如,如果建 模了一个数据库管理员和一个备份管理员,然后发 现他们的工作中有一部分是重叠的,那么,就可以创建一个称为系统管理员的参与者作 为数据库管理员和备份管理员 的泛化。
2 、 扩展关系
扩展是两个用例之间的关系,它使得每个用例可以通过扩展用例向基用例中添加 额外的行为来扩展基用例的功能。用例的扩展机制允许从一个基用例开始开发一个复杂的系统 ,并且能够在不改 变基用 例的前提下向基用例中扩展更多的行为。用例 A 扩展了用例B,则 A称为扩展用例( ExtendUseCase )或子用例,B称为基用例,它表示扩展用例 A的事件流在一定的条件下按照相应的扩展点可插 入基用例B中,这就需要在基用例中定义一至多个巳命名的扩展点。选用扩展关系可以 把一些可选 的操作独立封装 在另外的用例中,避免基用例过于复杂。
扩展关 系用虚 线加上开箭 头来表示。扩展用例被连接在箭头的尾部 ,箭头指向基用例,在虚线处添加一个<< extend> > 表示扩展关系。例如,在基用例Compare Inventory中,如果库存 量足够多,则可以启动零配件出库的功能,如果库存量不足则需要创建采购合 同。所以Stock Out和Create Purchas e Contract 是在用例 Compare Inventory基础上的扩展 ,可将 其建模为扩展关 系,如图2-11所示。

3、包含关系
包含是两个用例之间的关系。当多个用例需要用到同一段行为时 ,可以 把这段共同的行为单独抽象成为一个用例,然后让其他的用例来包含这一用例,从而避免在多个用例中重复描述同一段行为,也 可以 防止该段行为在多个用例中的描述出现不一致性。当需要修改这段公共的需求时,也 只 需 要 修 改一个用例,避免同时修改多个用例而产生的不一致性和重复性工作。用例 A包含 B,将 A 称为基用例,B 称 为被包含用例(I nc l us io n Use Cas e )。包含关系表示基用例会用到被包含用例,被包含用例的事件流在基用例的某个点处插入到基用例的事件流中。
值得注意的是,对 于 包 含关系而言,子 用 例 中 的 事件流是一定插入到基用例中去的,并且插入点只有一个,而扩展关系可以根据一定的条件来决定是否将扩展用例的事件流插入到基用例事件流,并且插入点可以有多个。包含关系是无条件的,扩展关系是有条件的。
包含关系用虚线加上箭头来表示。基用例被连接在箭头的尾部,箭头指向被包含用例,在虚线处添加一个 < < i ncl ud e > > 标 签以表示包含关系,如图 2- 1 2 所示。

在 PPS项目中,选择产品状态 ( ChooseProductCondition ) 会在许多场合下发生, 在创建销售订单和创建询价单中选择产品状态都是必不可少的活动,所以 把选择产品状态作为一个被包含的用例插入到 CreateOrder和 CreateEnquiry用例中,如果需要改动选择产品状态用例,则 不用 对 每一个用例都做相应修改 ,这样就提高了用例模型的可维护性。
图 2- 13 给出了 PPS 项目经过调整之后的部分用例。


2.4 总 结
至此,我们应用用例建立了初步的需求模型。应该避免这样一种误解——-认为U ML 的用例图就是用例。
用例模型主要用于描述系统的行为(功能)以及行为之间的关系。用例图从用户 的角度分析和考察系统的行为,并通过参与者与系统之间的交互关系描述系统对外提供 的 功能特性。用例图由参与者、用例和它们之间的关系组成。
这里还要说明一下用例规约。用例规约用于描述每一个用例的详细信息 ,这些信息应用用例的属性表示,用 例的属性将用例规约划分为若干逻辑块,规 定 了 每一个用例规约必须包含的内容,为一个给定项目的所有开发人员定义了用例规约的结构,但是它不属千 UM L 的内容。 Bit t ner 等人在 Use Case Model ing 中 对用 例的属性做出了总结,用例的属性主要包括:名称、参与者、简要描述、事件流、特殊需求、前 置条件、后置条件、扩展点和用例间的关系。本书附 录 B给出了 PPS 项目的部分主要用例的用例规约,供读者参考。

