使用UML建模现实世界的需求——实用指南
1. 引言
在现代软件开发中,用例图是从业务用户角度捕捉功能需求的基础工具。本案例研究详细分析了一个真实的用例图用于一个该平台的系统概述,使用PlantUML语法作为建模语言。目标不仅是展示用例图中使用了哪些元素,还展示了选择这些元素的为什么原因——突出展示实际建模决策、建模规范以及常见陷阱, 本案例研究既适用于,也适用于正在精进建模实践的从业者.
。它分解了图中的每一个元素,解释其用途,并讨论其在现实世界中的影响。2. 系统概述食品配送平台的系统概述该平台的系统概述
该平台的系统概述
该平台的系统概述该平台的系统概述是一个连接以下各方的数字市场:
-
顾客(订购食物的个人),
-
餐厅(餐食提供者),
-
司机(配送人员),
-
外部支付网关(处理交易的第三方系统)。
该平台使用户能够浏览餐厅、下单、跟踪配送、管理支付并应用促销活动。系统与支付处理器等外部服务集成,不会在内部处理支付逻辑。
PlantUML代码:
@startuml
skinparam monochrome true
skinparam shadowing false
从左到右方向
‘ 所有参与者均在矩形外部定义
actor 顾客
actor “注册顾客” as 注册顾客
actor “餐厅员工” as 餐厅
actor 司机
actor “支付处理器” as 支付网关
rectangle “外卖平台” {
(浏览餐厅)
(下单)
(跟踪订单)
(管理菜单)
(接收/准备订单)
(配送订单)
(处理支付)
(发放退款)
(应用优惠码)
(使用钱包)
(信用卡支付)
(数字钱包支付)
‘ 关联 – 箭头跨越边界
客户 –> (浏览餐厅)
注册客户 –> (下单)
注册客户 –> (跟踪订单)
餐厅 –> (管理菜单)
餐厅 –> (接收/准备订单)
司机 –> (配送订单)
支付网关 –> (处理支付)
支付网关 –> (发放退款)
‘ 包含
(下单) ..> (处理支付) : <<包含>>
‘ 扩展
(下单) <.. (应用优惠码) : <<扩展>>
(处理支付) <.. (使用钱包) : <<扩展>>
‘ 泛化
(处理支付) <|– (信用卡支付)
(处理支付) <|– (数字钱包支付)
}
‘ 执行者泛化(也适用于外部)
客户 <|– 注册客户
note right of PaymentGW
外部支付网关
(Stripe、PayPal、Adyen等)
结束注释
note bottom of (Apply Promo Code)
可选 – 仅在输入有效代码时
结束注释
@enduml
✅ 关键洞察: 该图关注的是外部交互——它展示了系统所做的事为用户和系统所做的事情,而不是其具体实现方式。
3. 图形元素:结合实际意义的深入解析
以下是图中使用的每个UML元素的全面解析,附带现实世界的解释和建模依据。
| # | 元素 | 符号 | 含义与目的 | 建模决策/注释 |
|---|---|---|---|---|
| 1 | 系统边界 | 矩形“外卖平台” |
定义了范围所建模系统的范围。所有内部的用例都属于该系统。 | 名称简洁但具有描述性。在企业环境中,可能会使用更长的名称(例如“客户订单管理系统”)。 |
| 2 | 主要人类参与者 | 参与者 客户, 参与者 骑手 |
代表外部角色启动或参与用例的。 | 名称简单直观。避免不必要的 stereotype,例如<<人物>>除非大型模型需要。 |
| 3 | 带别名的角色 | 角色 "餐厅员工" 作为餐厅 |
允许将较长的、描述性的角色名称缩短,以在连接中保持清晰。 | 当角色名称包含空格或较为冗长时非常有效。减少杂乱,提高可读性。 |
| 4 | 外部系统角色 | 角色 "支付处理器" 作为 PaymentGW |
建模第三方系统平台交互的系统。 | 无 stereotype«系统»不使用——在轻量级图中可接受。然而,添加«系统»可以在复杂系统中明确意图。 |
| 5 | 角色泛化 | `客户 < | — 注册客户` | 表示注册客户是访客客户. |
| 6 | 普通关联 | 顾客 --> (浏览餐厅) |
显示该参与者启动或参与用例。 | 实线 = 通信。方向从参与者指向用例(无需箭头)。 |
| 7 | «include» 关系 | (下单) ..> (处理支付) : <<include>> |
处理支付是始终必需在下单时。 |
箭头指向从包含者 → 被包含者。这一点至关重要:下单 包含 处理支付作为必需步骤。 |
| 8 | «extend» 关系 | (下单) <.. (应用优惠码) : <<extend>> |
应用优惠码是可选的并且仅在特定条件下发生。 | 箭头指向从扩展 → 基础. 基础用例(下单)可以扩展有条件地. |
| 9 | 用例泛化 | `(处理付款)< | —(信用卡支付)<br>(处理付款)< |
—(数字钱包支付)` |
| 10 | 备注 | PaymentGW 右侧的备注(应用优惠码)下方的备注 |
提供上下文解释关于实现或业务规则的说明。 | 备注被使用得不够充分,但极其有价值。它们可以防止误解(例如,说明 PaymentGW 是外部系统)。 |
| 11 | 边界外的参与者 | 所有参与者参与者声明位于矩形之前 |
强调没有参与者属于该系统—— 清晰的职责分离。 | 两种标准布局之一。当参与者众多或为外部时更推荐使用。 |
| 12 | 图表方向 | 从左到右的方向 |
当左侧有多个参与者时,可改善布局。 | 提升可读性。在4–8个参与者时尤为有效。替代方案:参与者较少时使用自上而下的布局。 |
4. 关键建模决策与理由
✅ 为何参与者位于系统边界之外
-
最佳实践:参与者代表角色在系统之外系统之外。
-
为何重要:避免系统组件与外部实体之间的混淆。
-
示例:
司机不是平台的一个模块——他们是与平台交互的第三方角色。
📌 专业提示:如果所有参与者都在边界内,就会暗示系统包含它们——这会造成误解。
✅ 为何使用客户 <|-- 注册客户而不是重复链接
-
如果没有泛化,你必须绘制:
客户 --> (浏览餐厅) 注册客户 --> (浏览餐厅) 注册客户 --> (下单) -
使用泛化后,你只需:
客户 <|-- 注册客户 客户 --> (浏览餐厅) 注册客户 --> (下单) -
结果: 更清晰、更易维护的图表。
📌 最佳实践: 当一个特殊参与者继承了更一般参与者的所有行为时,应使用参与者泛化。
✅ 为什么 <<包含>> 和 <<扩展>> 被正确使用
| 关系 | 目的 | 方向 | 示例 |
|---|---|---|---|
<<包含>> |
强制子流程 | 从 包括 → 被包含 | 下单 必须 包含 处理付款 |
<<扩展>> |
可选扩展 | 从 扩展 → 基础 | 应用优惠码 扩展 下单仅当代码有效时 |
❗ 常见错误:反转箭头方向。请始终记住:
包含:基础 ..> 包含
扩展:扩展 <.. 基础
✅ 为什么 处理支付具有泛化
-
信用卡支付和数字钱包支付是专门形式的处理支付. -
这表明该平台支持多种支付方式,但它们都遵循相同的主流程。
-
泛化允许共享行为和未来的可扩展性.
📌 用例:添加新的支付方式(例如 Apple Pay)只不过是另一种对的泛化
处理支付.
5. 现实世界中的解释与问题解答
此图不仅仅是一个视觉辅助工具——它回答了关键的业务和技术问题:
| 问题 | 来自图示的答案 |
|---|---|
| 主要用户是谁? | 客户、注册客户、餐厅员工、司机、支付网关 |
| 未注册用户可以下单吗? | ❌ 否——只有注册客户可以下单. 客户只能浏览餐厅. |
| 是否总是需要支付? | ✅ 是——下单 包括 处理支付. 必须的。 |
| 顾客可以使用优惠码吗? | ✅ 是的——但仅限于可选地通过<<扩展>>。只有输入有效代码时才可使用。 |
| 支持哪些支付方式? | 信用卡和数字钱包(通过通用化)。外部系统负责实际处理。 |
| 谁负责支付? | 外部支付网关——不属于平台的一部分。 |
| 餐厅可以管理他们的菜单吗? | ✅ 是的——餐厅参与者与管理菜单和接受/准备订单. |
✅ 业务价值:该图清晰地传达了系统的作用, 谁在使用它,以及哪些行为是强制性的,哪些是可选的.
6. 展示了常见的建模指南
该图例展示了几个最佳实践在UML用例建模中的
| 指南 | 如何应用 |
|---|---|
| 使用目标导向的用例名称 | 下单, 跟踪订单, 应用优惠码——全部以动词开头,描述用户目标。 |
| 保持图表可读性 | 仅显示10个用例——对于大多数业务领域来说是理想的(建议范围为5–12)。 |
| 将外部系统作为参与者 | 支付网关被建模为参与者而非用例。正确地分离了关注点。 |
| 使用注释来澄清歧义 | 注释说明支付网关是外部系统,且优惠码为可选——这对避免误解至关重要。 |
| 使用参与者泛化以减少杂乱 | “客户 < |
使用包含和扩展正确地 |
明确区分强制行为和可选行为。 |
📌 警告:许多图表误用
<<扩展>>来表示“可选”,而没有理解扩展的条件性。此图避免了这一错误。
7. 潜在改进与批评
虽然该图很出色,但以下是一些建设性建议用于优化:
🔧 1. 添加构造型以提高清晰度
参与者 "支付处理器" 作为 PaymentGW <<系统>>
-
原因:明确表明这是一个外部系统,而非人类角色。
-
好处:减少歧义,尤其是在大型模型中。
🔧 2. 明确应用优惠码扩展条件
目前:
注释:位于(应用优惠码)下方
可选——仅在输入有效代码时
结束注释
-
更好:使用条件标注或保护在……中
<<扩展>>箭头:
(下单)<..(应用优惠码):<<扩展>> [有效优惠码]
-
为什么:比注释更精确——直接将扩展与条件关联。
🔧 3. 考虑添加一个查看订单历史用例
-
目前缺失,但对顾客和餐厅来说可能都很重要。
-
可以作为
注册客户用例。
🔧 4. 分组相关用例(可选)
对于较大的图表,将用例分组为包:
包 "订单管理" {
(下单)
(跟踪订单)
(应用优惠码)
}
包 "支付" {
(处理支付)
(使用钱包)
(信用卡支付)
(数字钱包支付)
}
-
好处:提高可扩展性和可读性。
8. 下一步是什么?
本案例研究展示了如何通过结构良好的用例图能够清晰且简洁地捕捉复杂的业务逻辑。为了加深理解,以下是建议的下一步:
🔄 选项1:以餐厅为中心的视角
从以下角度建模相同的领域:餐厅的视角:
-
关注
管理菜单,接收/准备订单,查看订单,更新状态. -
显示
餐厅作为主要参与者。 -
包含
顾客作为次要参与者(例如,顾客发送订单 →餐厅接收订单)。
✅ 优势:揭示了不同的系统目标和参与者角色。
🔄 选项2:增加更多扩展点
增强下单 与:
-
应用优惠券(如果促销代码无效 →<<扩展>>带有错误消息) -
请求特殊说明(可选) -
安排订单(用于未来配送)
🔄 选项3:比较 包含 对比 扩展 带示例
| 用例 | <<包含>> |
<<扩展>> |
|---|---|---|
下单 → 处理付款 |
✅ 必须 | ❌ 不可选 |
下单 → 应用促销代码 |
❌ 非必须 | ✅ 条件性 |
登录 → 验证身份 |
✅ 始终需要 | ❌ 不适用 |
结账 → 应用折扣 |
✅ 始终 | ✅ 仅当存在折扣时 |
📌 经验法则:
使用
<<包含>>当行为发生时 必须发生.使用
<<扩展>>当行为发生时 可能发生 在某些条件下。
🔄 选项4:转换为序列图或活动图
用于更深入的分析:
-
序列图:展示流程的
下单→处理付款→交付订单通过参与者与系统之间的消息。 -
活动图:对 中的决策点进行建模
处理支付(例如,卡片被拒 → 重试或切换到钱包)。
9. 结论
本案例研究证明了一个精心设计的用例图 远不止是一个视觉草图——它是一种战略沟通工具 ,具体包括:
-
明确系统范围,
-
捕捉业务规则,
-
指导开发,
-
防止误解。
该食品配送平台 图示是一个强有力的范例 ,具体包括:
-
正确使用UML符号,
-
合理的建模决策,
-
清晰的关注点分离,
-
有效使用注释和泛化。
通过遵循此处展示的原则——目标导向的命名, 正确使用 include/扩展, 参与者泛化,以及注释的战略性使用——你可以创建既符合以下要求的用例图准确又可操作.
✅ 最终要点
| 原则 | 此处适用吗? | 为何重要 |
|---|---|---|
| 使用以目标为导向的用例名称 | ✅ 是 | 提高清晰度和用户关注点 |
| 保持图表大小可控 | ✅ 是(10个用例) | 防止认知过载 |
| 将外部系统作为参与者 | ✅ 是 | 正确地分离关注点 |
| 使用注释提供上下文 | ✅ 是 | 防止误解 |
| 使用泛化来减少冗余 | ✅ 是 | 使图表可扩展且易于维护 |
正确<<包含>> 和 <<扩展>> 方向 |
✅ 是 | 确保准确的行为建模 |











