1.3 UML的使用
1.3.1 UML的概念
UML统一了面向对象的Booch、OMT和OOSE等方法的建模语言,于1997年被OMG(Object Management Group,对象管理组织)接纳为软件开发标准,并于2005年作为ISO(International Organization for Standardization,国际标准化组织)标准发布。作为建模语言,UML共包括13种图,分为结构图、行为图和交互图,分别用于表达软件结构(Structure)、行为(Behavior)和对象交互(Interaction)模型。
UML结构图(Structure Diagrams)一般用于表达软件框架或架构,包括类图(Class Diagram)、对象图(Object Diagram)、包图(Package Diagram)、部署图(Deployment Diagram)等。其中,类图是面向对象分析和面向对象设计的核心,可用于表达概念模型和设计模型。
UML行为图(Behavior Diagrams)一般用于可视化目标软件的行为或服务模型,包括用例图(Use Case Diagram)、活动图(Activity Diagram)、状态机图(State Machine Diagram)等。用例图是可视化软件(功能)服务模型的重要方式,对软件开发人员更好地捕捉或理解软件需求有很大的帮助。用例驱动开发(Use Case Driven Development)是很多迭代或增量软件过程模型采用的重要开发方法,如统一过程、敏捷开发等。
UML交互图(Interaction Diagram)一般用来展示软件内部控制流或数据流模型,包括时序图(Sequence Diagram)、通信图(Communication Diagram)等。时序图通常作为对象交互模型的可视化手段,用于表达对象之间的协作关系。
1.3.2 使用用例图
用例是目标系统业务过程(Business Process)的抽象,由参与者(Actor)与系统的交互步骤(或事件)组成,参与者通过用例完成具体的业务目标。用例描述包括序号、用例名称、参与者、前置条件、后置条件、主业务流程及分支业务流程等,表1.1所示的是COS系统的注册用例描述示例。
表1.1 COS系统注册用例
系统用例模型通过UML用例图进行可视化。UML用例图基本符号有用例(椭圆形标识)、参与者(人形标识)、系统边界(矩形标识)、关联(直线标识),如图1.5所示。
图1.5 UML用例图基本符号
在图1.5中,系统边界表达(子)系统的用例范围,用以界定该(子)系统向外部环境提供的功能(或服务)。一般地,用例名称用动词加宾语的形式定义;参与者与用例之间的关联用直线表示,所有用例都有参与者,参与者可以是系统用户或与当前系统有交互关系的第三方(子)系统。参与者触发用例的业务流程,用例的业务结果需要以消息或视图的方式向参与者反馈。
运用UML用例图进行用例建模的步骤如下。
(1)抽取抽象用例:依据客户(或用户)提供的系统需求,分析人员可以通过头脑风暴(Brainstorming)等方式对业务过程进行分类,从而确定目标系统提供的(功能)服务。
(2)识别用例参与者:针对步骤(1)中的业务过程,分析与系统有交互关系的外部对象,得到每个业务过程的参与者角色。
(3)定义(子)系统边界:根据(子)系统向外部环境提供的服务范围,确定其所包含的用例。
(4)绘制用例图:按照UML用例图规范,对用例模型进行可视化。
(5)审查和改进用例模型:根据系统(或用户)需求审查用例模型,提出改进建议或迭代用例模型。
用例模型能够表达目标系统向外部环境提供的(功能)服务,也可以作为技术人员沟通软件需求的语言,或用于指导软件设计、软件测试等。图1.6所示的是COS系统需求的部分用例图示。
图1.6 COS系统需求的部分用例
图1.6中,“订餐”“删除订单”“取消订单”“支付订单”等是系统向外部环境提供的(功能)服务;“客户”“工资抵扣系统”“库存系统”等是与系统有交互关系的参与者角色。其中,“客户”参与的业务过程有“订餐”“删除订单”等,“工资抵扣系统”参与的业务过程有“支付订单”“注册支付方式”等,“库存系统”参与的业务过程有“订餐”等。
用例建模是面向对象软件分析的重要技术和方法,开发人员在使用用例图进行用例模型可视化时需要注意如下事项。
(1)用例图无法可视化非交互或非功能性的系统需求。
(2)用例的定义没有统一标准。
(3)复杂系统用例模型的全局可视化可能会降低用例图的可用性等。
1.3.3 使用时序图
UML时序图通过对象、消息、交互顺序等方式可视化软件业务过程中的控制流或数据流。时序图中的对象通过发送消息和接收消息进行交互,消息具有先后顺序。UML时序图基本符号有对象、消息、对象生命线、消息组合片段、终止符号等,如图1.7所示。
图1.7中,对象用矩形符号加垂直虚线标识,垂直虚线用于表示该对象的生命周期;消息使用带箭头的直线标识,箭头指向接收消息的对象;消息组合片段用矩形加组合类型标识,通过水平虚线进行消息分组。当对象需要销毁或生命周期终止时,在对象生命线的下方标注终止符号。
图1.7 UML时序图基本符号
时序图可用于可视化目标(子)系统内部对象的交互模型,以图形符号的形式表达对象之间的交互关系、交互顺序、对象生命周期等逻辑。软件技术人员利用时序图可以清晰地捕获业务场景中的对象、消息和对象交互方式,为软件设计或实现提供参考。
使用UML时序图进行目标(子)系统对象交互建模的步骤如下。
(1)找到需要进行对象交互建模的用例(或业务功能)步骤(或事件)。并不是所有用例(或业务功能)步骤都需要进行对象交互建模,开发人员可以依据“该步骤是否需要进行业务计算或数据管理”等逻辑判断需要建模的用例步骤。对于逻辑简单的用例(或业务功能)步骤,开发人员在熟悉业务需求的基础上,可以不进行对象交互建模。
(2)对目标步骤进行业务情景分析。由于开发人员对目标步骤不能清晰地知道“有哪些对象参与业务交互”,所以他们需要基于业务过程的需求分析,对该步骤进行情景建模,从而获取准确的业务过程情景模型。
(3)识别业务情景中的对象。业务过程情景模型中含有大量的对象、消息及对象交互关系,找出这些有用的信息对建模至关重要。
(4)识别业务情景中的消息。对象之间的协作关系依赖发送和接收消息建立,业务过程情景模型中的消息是模型可视化的必要元素。
(5)对象交互模型的可视化。使用对象、消息等图形元素将业务过程情景模型进行可视化表达。
(6)模型审查与优化。依据客户(或用户)需求,对建模结果进行分析,如果需要优化,则进入下一个模型迭代周期。
图1.8所示是COS系统中客户登录流程的获取验证码时序图。
首先,客户在登录界面输入“手机号码”,并提交“获取验证码”请求;“登录界面”向“验证码控制器”对象发送“获取验证码”消息;“验证码控制器”向“验证码生成器”对象发送“生成验证码”消息,结果返回为“验证码”;“验证码控制器”创建“结果消息”对象。然后“验证码控制器”判断“验证码”是否为空,如不为空,向“结果消息”中添加成功信息,并向“短信发送子系统”发出“发送验证码”消息;如为空,则向“结果消息”中添加失败消息。最后,“验证码控制器”向“登录界面”返回“结果消息”,“登录界面”向客户显示“结果消息”。
图1.8 COS系统中客户登录流程的获取验证码时序图
使用时序图进行对象交互模型可视化时,需要注意以下事项。
(1)消息类型有同步消息、异步消息、返回消息、自关联消息等。
(2)如果需要在时序图中标注对象生命周期终止,可以使用终止符号。
(3)可以对时序图标注对象类型(Type)和构造类型(Stereotype)。
(4)当系统内部对象需要和系统外部环境交互时,可以将外部环境(第三方系统或用户)标注为对象。
1.3.4 使用类图
类是面向对象软件分析和设计的核心目标。类定义了静态代码逻辑,是软件内部对象的泛化(Generalization)类型;对象是类的实例;类的关联是对象协作逻辑的静态表示。采用面向对象方法实施软件编码活动的本质是定义类。
UML类图可用于表达软件系统的静态结构,基本符号包括类(矩形)、类关系(直线、带箭头直线、带菱形直线等)等,如图1.9所示。
图1.9 UML类图基本符号
UML类图可用于描述类的名称、域和方法等。类名称是对象泛化的结果,具有概括或抽象特性。一般使用对象在业务领域中的角色名称命名类,如学生、老师等。类的域是类属性(或特征)的定义,包括域名称、可见性、域类型等。类的方法是类行为(或服务)的定义,包括方法名称、可见性、方法参数、返回类型等。
面向对象编程语言Java支持的类(和对象)关系类型有关联(Association,分为单向关联和双向关联,用带箭头的直线标识,箭尾指向维护关联关系的类;双向关联省略箭头)、依赖(Dependency,用带箭头的虚线标识,箭头指向被依赖的类)、组合/聚合(Composition/Aggregation,用带菱形的直线标识,菱形指向聚合体类)、继承/实现(Inheritance/Realization,用带三角形的直线/虚线表示,三角形指向父类/接口)等。
需要指出的是,依赖是类或对象之间最普通的关系,关联、组合/聚合、继承等是依赖关系的一种业务类型。例如,类A的变化会引起类B的变化,则定义为类B依赖于类A。在代码形式上的区别有以下3点。
(1)依赖对象可以将被依赖对象作为方法的传入参数、返回参数或局部变量;
(2)关联对象通常将被关联对象定义为成员变量或静态引用;
(3)聚合体对象通过设值(Setter)或构造方法初始化聚合元素对象;而组合对象则在其内部行为中创建或初始化聚合元素对象。
使用类图可以表达目标系统的领域模型或设计模型,一般步骤如下。
(1)识别类:可以通过对象业务角色或多个对象泛化(或抽象)角色筛选类信息。
(2)识别域和方法:域用于描述类的特征,业务含义依赖于目标类;方法是类的业务行为表达。
(3)抽取类关系:类关系大多是业务关联关系,包括多样性定义、关联名称等。
(4)模型可视化:将类、类关系通过类图的方式进行模型可视化展示。
(5)模型审查与优化:根据需求对可视化模型审查,如提出修改建议,则进入下一阶段模型迭代。
图1.10所示的是COS系统部分需求的领域模型示例。
图1.10 COS系统部分需求的领域模型
在图1.10中,“客户”订购“套餐”、支付“订单”和浏览“菜单”;“套餐”包含若干“菜品”,“菜单”中包含“菜品”和“套餐”;“客户”支付“订单”的业务关联生成“支付单”;“客户”订购“套餐”的业务关联生成“订单”。
类图不仅可以用于呈现需求的业务领域模型,也可以用于表达逻辑代码的设计模型,如图1.11所示。
图1.11 COS系统部分设计类
(注:由于大多软件编程语言用英文编写,所以软件设计模型用英文标注更符合编程模型的表达习惯)
图1.11中的设计类可以直接通过Java语言翻译成框架代码,再辅以业务详细设计的程序流程(或算法),可以直接输出为软件业务实现代码,例如,Patron类代码框架如下。
public class Patron extends Employee { private String name;// 客户名称 private PatronLevel level;//客户等级 private PayOrder payOption;//支付方式 / ** * 支付订单行为,返回支付账单 * / public PayBill pay(){ //支付订单逻辑 //return 语句 } }
使用类图进行建模时,须注意如下事项。
(1)类图可以呈现域、方法和类关系等代码要素,但无法表达详细业务流程。因此,如果只有类图模型,则并不能直接进行程序实现。
(2)类图文档通常与代码实现不一致,且更新代价较高。
(3)从静态代码形式上看,不同的类关系代码形式常常相同或相似。因此,一般按系统对象的角色或业务职责区分类关系。