使用 StarUML 绘制 UML


UML 架构及 StarUML

UML 架构

UML 图形分类:

  • 对象图 + 类图 + 组件图 + 部署图
  • 交互图 + 用例图 + 时序图 + 协作图 + 活动图
  • 状态图 + 状态图

参考文档

这里重点学习 用例图、时序图 和 类图 三张图.

StarUML

StarUML 5.0 貌似是最后一个免费版本…

安装好后运行, 会让选一个 approach (入口), 直接点 Cancel 就好, 会以默认的视图打开 StarUML.

也可以选择 Rational, 这种 approach 用的也比较多.

  • 用例视图(Use Case View), 包含系统中所有的参与者、用例和用例图, Use Case View 在系统中可以看成是一个独立的实现, 它侧重用高级别的视图表明系统做什么, 而不用考虑具体的实现

  • 逻辑视图(Logical View), 重点描述在系统中如何实现用例, 它提供系统各模块的详细视图, 并描述这些模块之间的关系, Logical View 包含对一些类图、时序图和状态图, 通过这些具体的元素, 开发者可以对系统构建具体的设计

  • 组件视图(Component View), 包含的信息有代码库、可执行文件、运行时库,还有在模型中的其他组件, 一个组件就是一个物理的编码模块

  • 发布视图(Deployment View), 关于系统的物理发布, 它不同于系统的逻辑架构

UML 用例图

用例, 是帮助角色确定系统使用情况的 UML 组件

用例组, 是从用户角度出发对如何使用系统的描述

用例图, 用图形的方式来描述情景, 主要用来描述 “用户需求系统功能单元” 之间的关系, 它展示了一个外部用户能够观察到的系统功能模型, 也就是说, 它应该是从用户的角度来描述系统, 而非开发者.

用例卡片

在用例图出现之前, 当需要去客户那讨论某些功能的需求时, 常常会带上一堆的 “卡片”, 每张卡片上都是一张用例表单, 讨论过程中按照客户的要求填写这个表单, 等讨论结束, 就按这个表单的内容进行开发, 这个记录了需求表单的卡片, 就叫它 “用例卡片”, 下面是一个登录功能的用例卡片.

用例图

通过这张卡片, 可以总结出一些用例要素:

  • 参与者 + 包括使用者、系统用户和其它交互的系统
  • 前置条件
  • 场景中的步骤 + 事件流
  • 后置条件

StarUML 用例图

打开 StarUML, 选择 Rational Approach.

StarUML 界面右侧的 Model Explorer 中 <<use case view>> 就是用例图 view, 我们要添加用例图, 就要在这个 view 下添加.

<<use case view>> 自带了一个 Main 用例图, 点击下 <<use case view>> 下的 Main, 在StarUML 界面左侧, 就打开了用例图工具栏.

StarUML 翻译 功能
Package 分类、模块、子模块
类比文件夹的功能
UseCase 用例 描述一个用户的具体动作
要求是动宾短语
Actor 角色 执行者
包括用户、后台系统员或者其他系统
Association 关联 表示参与者与用例之间可以通信
DirecteAssociation 定向关联 也表示参与者与用例之间可以通信, 但是用箭头表示通信方向
箭头指向消息接收方
Generalization 泛化 继承关系
子用例和父用例相似, 但表现出更特别的行为
子用例将继承父用例的所有结构、行为和关系
箭头指向父用例
Dependency 依赖 源用例依赖于目标用例
如冰箱依赖插头, 去食堂吃饭依赖于有餐卡
箭头指向目标用例
Include 包含 用来把一个较复杂用例所表示的功能进行分解
包含属于依赖的一种
箭头指向分解出来的子用例
Extend 扩展 指用例功能的延伸
相当于在一定条件下为基础用例提供一个附加功能
如, 只有在书籍丢失用例成立的情况下才会触发补偿用例
箭头指向基础用例
System Boundary 系统边界 用来把一些联系紧密的用例包含起来
一般认为被包含的用例共同完成某一功能
而边界外的用例则与这个功能无关

Extend (扩展) 图样示例:

只有当 “失书” 的扩展点发生后, 才会触发补偿的用例.

小技巧:

当发现线条不规整时, 可选中该线条, 按 Ctrl + L 来自动规整.

对于每个图样, 可以在 StarUML 右下方设置其属性:

对于用例图来说, 我们只关心它的 Name 和 Stereotype 属性, 后面的 Visibility、IsAbstract、Attributes、Operations 在画类图的时候才会有所体现.

当然你也可以在 <<use case view>> 上右键选择新添加用例图:

<<use case view>> --> Add Diagram --> Use Case Diagram

在 StarUML 左侧, 除了 UseCase 的工具栏外, 还有一个注释工具栏 (Annotation), 这个工具栏是所有 UML 图形通用的:

StarUML 说明
Text 文本
Note 注释
NoteLink 注释连接线
Rectangle 矩形
Elipse 椭圆
Rounded Rectangle 圆角矩形

这里我们常用的是 NoteNoteLink.

小技巧:

当使用图形时, 可以在工具栏上设置图形的层次.

关于删除

如果你在 StarUML 画布上拖入某个图样, 那么直接在画布上删除仅仅是在画布上删除它, 它还是在右边的 Model Explorer 中, 必须要在 Model Explorer 中删除才是真的删除, 或者在画布上 Ctrl + Del 删除.

关于用例图设计

通常情况下, 一个系统可能会被我们分为几个模块, 每个模块都完成独立的功能, 我们把这些模块用 Package 表示, 在 Main 视图下列出大纲, 然后在每个 Package 下画各自的 UseCase, 如下图所示:

UML 状态图

状态图概述

状态图是一种”开关”, 描述的是状态变化的图形, 即一个对象状态状态的转变, 并且给出了状态变化的起点终点, 类比流程图.

使用场景

需要描述一个对象的状态跟踪的时候, 比如一个表单在不同环节审批的状态

在 StarUML 中新建状态图:

打开 StarUML, 选择 Rational Approach.

<<Logical View>> --> Add Diagram --> Statechart Diagram

界面左边就出现了 Statechart 工具栏.

StarUML 翻译
State 状态节点
SubmachineState 状态子节点
InitialState 初始状态
FinalState 结束状态
JunctionPoint 交汇点(两条状态传递线交汇处)
ChoicePoint 选择点(又叫进入节点)
ShallowHistory 浅层历史状态
DeepHistory 深层历史状态
Synchronization 同步
Flow Final 对象流程结束(退出节点)
Transition 状态传递
SelfTransition 自我状态传递

核心要素

对于状态图来说, 最为核心的元素无外乎是两个:

  • 一个是用圆角矩形表示的状态(State)
  • 一个则是在状态之间的、包含一些文字描述的有向箭头线(Transition), 这些箭头线称为状态传递

  • 源状态: 即受转换影响的状态
  • 目标状态: 当转换完成后对象的状态
  • 触发事件: 用来为转换定义一个事件, 包括调用、改变、信号、时间四类事件
  • 监护条件: 布尔表达式, 决定是否激活转换
  • 动作: 转换激活时的操作

状态动作

状态节点有三个内部动作:

  • EntryActiors, 进入状态时触发的动作
  • DoActions, 状态中执行的动作
  • ExitActions, 退出状态时触发的动作

当然, 这三个事件都不是必须的, 根据需求来填写.

例如在上例中, 对象状态转移后的动作(烧水), 是显示在箭头线上, 也可以定义进入动作(EntryActions)来描述转换激活时的操作

复合状态

另外, 在某些时候, 还可以使用复合状态, 它表示在某一状态中, 还维护着其它的状态.

如, 在电脑运行的时候, 还会维护一个待机的状态.

退出/进入节点

上面的图中, 除了用到了复合状态外, 还使用了退出节点(Flow Final), 它表示状态可以有多个退出事件, 如上图中的 长按电源键 或者 断电, 都会触发 running 状态的退出.

除了退出节点(Flow Final)外, 还有个 ChoicePoint(选择节点, 又叫进入节点), 它表示一个状态有多个进入事件, 就不放图举例了.

子节点

再来看看 SubmachineState(状态子节点), 它所以表示的是该状态是另一个状态(称之为母状态)的子状态, 母状态中以引用的方式把一个已经存在的状态作为自己子状态, 在母状态机中子机状态作为一个子状态, 但它自身仍是一个完整的状态.

历史状态

ShallowHistory(历史状态), 为一个状态提供了一种在退出状态时记忆当前活动所处的子状态, 并能够返回到该子状态的机制.

例如下图, 当发生暂停时, 记住播放状态, 当继续播放时就直接进入播放状态.

StarUML 中有 ShallowHistoryDeepHistory, 但在大多情况下是随便用哪个, 并没有做太多要求, 只要表达清楚这里是一个”历史”就可以了.

同步

Synchronization 又分两种, 分叉与汇合.

  • 分叉: 指将一个转换分成两个或多个转换, 用来描述需要并发的状态
  • 汇合: 指将从并发状态来的转换合并形成一个转换, 用来描述多个并发状态的控制同步

UML 时序图

时序图概述

何谓时序图:

简单的说, 就是描述一个时间段内不同对象之间的业务情况(时间顺序).

时序图的重点在消息时序上, 也就是说, 描述消息是如何在对象间发送和接收的, 表示了对象之间传递消息的时间顺序.

时序图与用例图:

时序图表示了系统参与者互动执行某一个用例期间, 系统内部对象间的协作情况.

对于程序设计来说, 一个用例就对应一个时序图, 时序图是对系统的内部行为进行描述, 用于用例分析和设计阶段.

在项目的需求阶段, 架构师会根据把用例图细化为一个或者更多的时序图.

虽然在开发者看来, 时序图描述的是模块(类)间的交互, 然而, 现在时序图也常常被业务人员用来描述业务的流程.

在 StarUML 中新建时序图:

打开 StarUML, 选择 Rational Approach.

<<Logical View>> --> Add Diagram --> Sequence Diagram

界面左边就出现了 Sequence 工具栏.

StarUML 翻译
Object 对象
Stimulus 消息传递
SelfStimulus 自我消息传递
Combined Fragment 组合碎片
Interaction Operand 交互操作域
Frame 框架

Object

时序图中 Object 的命令遵循下面的格式:

实体名 : 类名

大部分情况下, 我们可能只关心类名, 所以可以简写成 : 类名.

Lifeline 与 Focus of Control

生命线在时序图中表示为从对象图标向下延伸的一条虚线, 表示对象存在的时间.

控制焦点生命线中表示时间段的符号, 在这个时间段内对象将执行相应的操作, 用小矩形表示.

Stimulus

消息类型

消息一般分为同步消息(Synchronous Message), 异步消息(Asynchronous Message)和返回消息(Return Message).

如下图所示:

  • 同步消息: 消息的发送者把控制传递给消息的接收者, 然后停止活动, 等待消息的接收者放弃或者返回控制
  • 异步消息: 消息发送者通过消息把信号传递给消息的接收者, 然后继续自己的活动, 不等待接受者返回消息或者控制
  • 返回消息: 返回消息表示从过程调用返回

对于 StarUML 而言, 同步消息的 Stimulus 为 Call, 异步消息的 Stimulus 为 Send, 返回消息的 Stimulus 为 Return.

消息约束

当为对象的交互建模时, 有时候必须满足一个条件消息才会传递给对象.

为了在一个序列图上画一个约束, 你把约束元件放在约束的消息线上, 消息名字之前.

注意 Stimulus 上的 [restraint == true].

Combined Fragment

Combined Fragment 用来描述一批 Stimulus 的约束, 如上面 消息约束 中的 [restraint == true], 如果想要其对多条 Stimulus 生效, 就可以使用 Combined Fragment.

只有当 restraint == true 时, Combined Fragment 里的 Stimulus 才会被触发.

Combined Fragment 左上角的 opt 表示选择约束, 除了 opt 外, 还有 loop(循环), 甚至还支持 if else 结构(alt).

不过要使用 alt, 就要配合 Interaction Operand 了, 把 Interaction Operand 拖放到 Combined Fragment 里就可以对 Combined Fragment 进行拆分了, 效果如下:

如果 restraint == true, 则执行 call_1(), 否则执行 call_2().

UML 协作图、活动图

协作图

协作图时序图 是可以互转的, 只不过一个重点表达时序的先后关系, 一个重点表达对象间交互关系.

通常 时序图 用的更多, 而协作图的主要作用是显示某个组件/对象是否有过多的交互, 是否应该继续分拆, 它可以当作时序图的辅助形式.

活动图

活动图 就是最早就接触过的 流程图, 至少在画法上, 活动图和流程图很相似, 但 UML 活动图是面向对象, 表示的是对象间的流程.

从存在意义上说, 活动图时序图一样, 都是对用例图的再分析, 不同的是, 时序图是从计算机角度出发, 而活动图是从用户角度出发, 因此, 对于我们开发者来说, 活动图在表示上”不够技术性”, 但对业务人员来说, 往往能够更快速地理解它们.

根据我的经验, 当我们拿到用例图后, 可以先用时序图来尝试, 当发现用时序图不怎么好实现时, 再转向使用活动图, 毕竟有些复杂的交互, 用计算机的角度并不一定能描述清楚.

总结

协作图活动图 两张图不做太多要求, 知道下就好.

UML 类图

类图概述

类图, 豪不夸张的说, 是 UML 里最复杂的图了…

类图在需求阶段和设计阶段具有不同的含义, 参考我之前的一篇笔记: 正确辨析类图的两种存在形式

对于我们开发者来说, 我觉得重点还是在设计阶段的类图.

在 StarUML 中新建类图:

打开 StarUML, 选择 Rational Approach.

<<Logical View>> --> Add Diagram --> Class Diagram

界面左边就出现了 Class 工具栏.

StarUML 翻译
Subsystem 子系统
Package
Class
Interface 接口
Enumeration 枚举
Signal 信号
Exception 异常
Port 端口
Part 局部
Association 关联
DirectedAssociation 定向关联
Aggregation 聚合
Composition 组合
Generalization 泛化
Dependency 依赖
Realization 实现
AssociationClass 关系类
Connector 连接
Object 对象
Link 链接

UML 部署图

是用来建模系统的物理部署, 例如计算机和设备, 以及它们之间是如何连接的, 部署图的使用者是开发人员、系统集成人员和测试人员.

如果含有依赖关系的构件实例放置在不同节点上, 部署视图可以展示出执行过程中的瓶颈.

UML 组件图

描述代码构件的物理结构以及各种组件之间的依赖关系, 在组件图中, 组件可以是一个文件、产品、可执行文件或脚本等.

在 UML 2 中, 组件被认为是独立的, 在一个系统或子系统中的封装单位, 提供一个或多个接口.

虽然 UML 2 规范没有严格地声明它, 但组件是呈现事物的更大的设计单元, 这些事物一般将使用可更换的组件来实现.

主要思想是, 你能容易地在你的设计中重用或替换一个不同的组件实现, 因为一个组件封装了行为, 实现了特定接口.

在这里, 初学者很容易将组件图和类图搞混, 那么组件图和类图的区别如下:

  • 类表示的是逻辑的抽象, 构件是存在于计算机中的物理抽象, 组件是可部署的, 而类不行
  • 组件表示的是物理模块, 类是逻辑模块, 组件是由一组类协作而成的
  • 类可以直接拥有操作和属性, 组件仅拥有可以通过其接口访问的操作

参考文档

部署图和组件图:

  • 部署图表现组件实例, 偏向于描述组件在节点中运行时的状态, 描述了组件运行的环境
  • 组件图表现组件类型的定义, 偏向于描述构件之间相互依赖支持的基本关系

先有部署图还是组件图? 依照 top down 原则, 所以是从部署图到构件图, 实际上也应该如此, 因为我们在需求确定后, 一般就会确定大体的技术架构、程序模块划分, 而此时一般系统集成的工作也要相应的启动: 要买主机、网络设备; 所以要提供给系统集成人员相应的资料, 那么就需要先把部署图做出来, 然后再细化构件图.