从“游客”到“管理员”:拆解一个复杂系统的UML用例图
第一次接手航空购票系统的需求文档时,我盯着那三页模糊的业务描述发了半小时呆。产品经理只告诉我"系统要支持用户买机票、退机票,还要跟信用评价挂钩",但具体哪些角色会参与?系统边界在哪里?用例之间的依赖关系如何设计?这些问题都需要从零开始梳理。作为系统分析师,我的任务就是把这段模糊文字转化为清晰的UML用例图——不是简单地画几个椭圆和箭头,而是通过严谨的分析过程,揭示系统真正的行为逻辑。
1. 参与者识别的思维陷阱
当我开始分析航空购票系统时,第一反应是列出所有可能"使用"系统的人或物。但很快发现这种直觉式列举存在严重缺陷——把"参与者"等同于"用户角色"是新手最常见的建模误区。
1.1 主参与者与副参与者的本质区别
真正的参与者分析需要区分两类关键角色:
- 主参与者(Primary Actor):通过触发用例获得直接价值的主体
- 副参与者(Secondary Actor):为用例完成提供必要服务的辅助角色
以"退订机票"用例为例:
| 参与者类型 | 实例 | 价值主张 |
|---|---|---|
| 主参与者 | 注册用户 | 解除已购机票的绑定 |
| 副参与者 | 信用评价系统 | 更新用户信用数据 |
这个区分直接影响用例图的布局——主参与者通常位于左侧,副参与者位于右侧,形成清晰的价值流动方向。
1.2 抽象参与者的识别技巧
在梳理用户角色时,我发现系统存在明显的层级关系:
用户(抽象) ├─ 游客(具体) └─ 注册用户(具体)这种泛化关系(Generalization)的识别有四个判断标准:
- 是否存在"是一种(is-a)"的关系
- 子类型是否完全继承父类型的所有用例
- 父类型是否永远不会被直接实例化
- 子类型是否新增特有行为
通过这个检查清单,我确认"用户"应该作为抽象参与者存在,而"游客"和"注册用户"是其具体实现。这种设计大幅减少了用例图中的重复关联——例如"查询航班"只需要关联到抽象用户,无需分别关联游客和注册用户。
2. 用例提取的黄金法则
从需求文档到用例列表的转化过程,就像把散文改写成诗歌——需要保留核心语义,同时建立精确的结构。我总结出三条黄金法则:
2.1 动词-名词结构的强制约束
每个用例名称必须符合动词+名词结构,例如:
- ✅ 购买机票(符合)
- ❌ 机票购买流程(不符合)
这种约束强制我们聚焦于系统的行为而非状态。在初期分析中,我列出了以下候选用例:
1. 注册账号 2. 登录系统 3. 查询航班 4. 选择航班座位 5. 支付订单 6. 查看行程 7. 取消预订 8. 评价服务通过合并相似行为(如"选择航班座位"本质是"购买机票"的子步骤),最终精简为6个核心用例。
2.2 用例粒度的平衡艺术
用例的粒度把控是最考验分析师功力的部分。我的经验法则是:
- 单个用例的执行时间通常在2-10分钟
- 用例应该产生业务方可感知的价值
- 技术细节(如"验证密码强度")不应作为独立用例
例如"购买机票"可以拆分为:
- 选择航班
- 填写乘客信息
- 支付订单
但作为业务分析师,我选择保持较高粒度,因为拆分会破坏"完成一次完整购票"的业务语义。
2.3 包含与扩展关系的实战判断
用例关系的误用是UML图中最高频的错误。通过信用评价场景,我总结出以下决策树:
是否必须执行? → 是 → 包含关系(include) ↓ 否 → 是否有条件触发? → 是 → 扩展关系(extend) ↓ 否 → 独立用例应用示例:
- 包含关系:"购买机票"必须"检查信用等级"
- 扩展关系:"退订机票"可能触发"降低信用等级"
- 独立用例:"修改个人资料"不依赖其他用例
3. 工具实操中的隐藏细节
使用Enterprise Architect绘制用例图时,我发现几个教科书上没讲的实用技巧:
3.1 参与者布局的视觉优化
通过工具包中的对齐辅助线(Alignment Guides),可以构建更专业的布局:
1. 选中所有参与者 2. 右键选择"Align" → "Left Edges" 3. 拖动参考线调整间距为1.5cm这种视觉规范虽然不影响逻辑正确性,但能显著提升图形的可读性。
3.2 用例关系的方向调整
当关联箭头方向不符合习惯时,可以通过以下步骤修正:
- 双击关系线打开属性窗口
- 导航至"Style"选项卡
- 修改"Source/Target Style"中的箭头方向
- 勾选"Show Direction"复选框
提示:EA默认的关联方向可能不符合UML规范,建议始终手动检查
3.3 用例规约的模板应用
每个用例都应该有详细的文本描述,EA提供了标准模板:
| 字段 | 示例内容 |
|---|---|
| 前置条件 | 用户已登录且信用等级≥B |
| 后置条件 | 订单状态变更为"已取消" |
| 主事件流 | 1. 用户选择待退订的机票... |
| 异常事件流 | 1a. 机票已过退订期限... |
在项目浏览器中右键点击用例,选择"Properties" → "Scenario"即可填写。
4. 复杂边界的处理策略
当系统与外部服务交互时,用例图需要特殊处理。信用评价系统带来的挑战尤为典型。
4.1 外部系统的建模方式
信用评价系统作为独立系统,在用例图中应该:
- 用不同的颜色标记(如浅灰色)
- 添加
<<external>>构造型 - 明确标注交互协议(如REST API)
在EA中可以通过修改Actor的填充色实现:
<actor xmi:id="CreditSystem" name="信用评价系统"> <style fillColor="#CCCCCC"/> <stereotype name="external"/> </actor>4.2 跨系统用例的拆分原则
涉及多系统协作的用例需要明确责任边界:
- 检查信用等级:
- 主系统:发起查询请求
- 外部系统:返回信用评分
在用例规约中应该分别描述两边的行为流,并通过接口契约定义数据格式。
4.3 异常流的特殊处理
当外部系统不可用时,需要设计降级方案。例如:
注意:信用检查超时应允许继续购票,但需记录审计日志
这种业务决策必须明确记录在用例的"异常事件流"中,而不是隐藏在代码实现里。
5. 从用例图到需求矩阵
完整的分析过程应该产出可追溯的需求矩阵。我创建的跟踪表包含以下字段:
| 需求ID | 用例名称 | 参与者 | 优先级 | 业务规则 |
|---|---|---|---|---|
| REQ-01 | 退订机票 | 注册用户 | 高 | 每月前两次免费退改 |
| REQ-02 | 降低信用等级 | 信用评价系统 | 中 | 退票超过两次触发 |
| REQ-03 | 查询航班 | 用户(抽象) | 高 | 支持按价格/时间/航司过滤 |
这种映射确保每个业务需求都有对应的建模元素,避免遗漏关键场景。