苏晶
山东理工大学 山东 淄博 255049
UML用例模型是系统需求获取及分析的重要手段,是最终用户与开发人员沟通和交流的有效途径。一旦用例模型被确定,所有分析、设计和开发,包括之后的部署及测试等工作都需要以此为依据开展。
对于一个系统而言,不同参与者的需求千差万别;另外,为了确保系统安全性,也需要为不同的参与者设置不同的访问功能和权限。在系统分析和设计过程中,关系直观体现了参与者访问系统功能的具体方式,并直接影响和决定了系统的具体实现方式。由此可以看出,关系的识别在构建用例模型的过程中发挥着至关重要的作用。
其中包含关系和泛化关系在表现形式和使用方法上较为相似,容易产生混淆,本文以自主点餐系统为例,对两种关系的建模要点进行分析和比较。
包含关系是指一个用例可以简单地包含其他用例具有的行为,并将其所包含的用例行为作为自身行为的一部分,这两个用例分别被称为基础用例和被包含用例。包含关系的具体表现形式为被包含用例的事件流可插入至基础用例的事件流中。
在用例图的建模过程中,一般有两种情况需要使用到包含关系。第一种最为常用,在对用例的事件流进行描述的过程中,若发现多个用例同时使用到同一段行为,则可将这段共同的行为单独抽象成为一个用例,然后建立两者之间的包含关系,从而实现重用并简化事件流描述的目的。
以自主点餐系统为例,客户可以进行“预约餐台”、“下单点餐”、“支付结算”和“发表评价”四个操作,所有操作均需在“登录系统”后方可完成。根据描述,“登录系统”为多个用例的共同行为,可将其抽象出来,成为一个新的用例,并建立其与4个基础用例之间的包含关系。关系一旦创建,这4个基础用例在用例规约的事件流描述中可直接对“登录系统”用例的事件流进行引用,避免了对公共行为的重复描述,提高了模型的可维护性。
包含关系使用的第二种情况为某一个用例提供的功能过多,事件流过于复杂,此时可将该用例分解为粒度较小的几个用例,然后建立分解后小用例与原来基础用例之间的包含关系。
如自主点餐系统中管理员的“维护菜品”操作,由于功能过多,可将其分解为“添加菜品”、“修改菜品”和“删除菜品”三个用例,则三个粒度较小用例与基础用例间可建立包含关系。需要注意的是,这种方式的包含关系不允许参与者直接访问包含用例,这也是两种包含关系之间最大的区别。
用例间的泛化关系将特化的用例与一般化的用例联系起来,这两个用例分别被称为子用例和父用例。子用例继承了父用例所有的结构、行为和关系,并且可以添加、覆盖或者改变继承的行为。
在对用例的事件流进行描述的过程中,发现两个或者多个用例在行为、结构和目的方面存在共性时,可以新建一个一般化的用例用于描述这些共有部分和一般过程,然后建立特化用例和一般化用例之间的泛化关系,从而实现重用并简化事件流描述的目的。
在自主点餐系统的功能性需求中,有这样一段描述,“支付结算”主要包括“支付宝结算”和“会员卡结算”两种方式。经过分析发现,“支付宝结算”和“会员卡结算”两个用例在行为、结构和目的方面都存在共性,都属于“支付结算”的特殊方式,因此可将其抽象为父用例,两种代表具体支付方式的用例抽象为子用例,建立泛化关系,并且箭头方向从子用例指向父用例。
需要注意的是,为了降低系统耦合度,一般将父用例设计为抽象用例,即在父用例中并不提供具体的行为和功能,而将行为描述的职责交给子用例来完成[1]。
包含关系和泛化关系均属于用例之间的关系,并且基本表现形式都是从现有用例的事件流中抽取出共有部分,将其作为一个单独的用例,从而达到复用现有用例的行为,并提高模型可维护性的目的。但两者在实际使用过程中又存在着显著的区别。
以自主点餐系统为例,分析两者的区别主要包括以下两个方面:
在泛化关系中,子用例“支付宝结算”和“会员卡结算”不管在名称、行为、结构还是目等方面都存在着共性,并且都属于“支付结算”的特殊形式,因此原有用例是整体上的相似。
而在包含关系中,基础用例“预约餐台”、“下单点餐”、“支付结算”和“发表评价”在名称、结构和目的方面可以完全不同,只不过它们都有一段相似的行为,也就是“登录系统”而已,因此原有用例只是部分上的相似。
在泛化关系中,需要将多个子用例中的共性抽象成为一个父用例,子用例在继承父用例的基础上可以进行修改,子用例间相互独立,任何一个子用例的执行不受其他子用例的影响。如果父用例“支付结算”为抽象用例,不提供具体的查看方法,则子用例“会员卡结算”被参与者启动后,父用例“支付结算”不会被执行。
而对于包含关系,是将多个基础用例中的公共行为抽象为一个被包含用例,可以说被包含用例是基础用例的重要组成部分,因此,基础用例“支付结算”被参与者启动后,被包含用例“登录系统”必然会被执行[2]。
用例图中的模型元素之间并非相互独立,参与者之间、用例之间、参与者与用例之间均存在着不同类型的关系。从用户层面来看,关系描述了模型元素间具体化的语义连接,反映了参与者使用系统的具体方式;从开发者层面来看,关系体现了事件处理的流程与协作,决定了系统功能的实现方式。因此,在用例建模过程中,需准确把握各种关系的使用方法和建模要点,避免因识别有误而对后续的设计和开发过程产生不利影响。