UML之用例图学习

一、用例图的本质定义

核心理念

用例图 = 从"系统外部"看系统能做什么

记住关键词:

  • 外部:站在系统外看
  • 能做什么:功能视角
  • 不关心怎么做:不涉及实现

重要原则:用例图不画流程、不画状态、不画代码

用例图的本质作用

  • 需求澄清:与客户/产品经理对齐功能边界
  • 系统范围界定:明确哪些在系统内,哪些在系统外
  • 功能清单:系统提供的所有对外服务
  • 测试依据:每个用例都对应一组测试场景

二、用例图在整个 UML 体系中的位置

复制代码
需求分析 → 用例图 → 行为图(活动图/状态图/时序图)→ 类图 → 代码实现
   ↑                                                              ↓
   └──────────────────── 需求追溯 ──────────────────────────────┘

用例图是所有 UML 图的起点,它回答:

  • 系统要做什么?(What)
  • 谁会使用系统?(Who)
  • 系统边界在哪?(Boundary)

其他图回答:

  • 活动图:流程怎么走?(How - Process)
  • 状态图:状态如何变化?(How - State)
  • 时序图:模块如何协作?(How - Interaction)
  • 类图:结构如何设计?(Structure)

三、用例图的 3 个核心元素(必须掌握)

1️⃣ 参与者(Actor)

定义:与系统交互的外部角色 ,是系统功能的发起者或接收者
Actor 可以是什么?
类型 示例 说明
用户、管理员、操作员 最常见的 Actor
设备 传感器、上位机、硬件控制器 嵌入式系统中常见
外部系统 数据库、云服务、第三方 API 系统集成场景
时间 定时器、调度器 触发定时任务
📌 关键判断标准
复制代码
✅ 正确的 Actor                  ❌ 错误的 Actor
------------------------------------------------------
- 用户                           - UART 模块(系统内部)
- 传感器                         - DMA 控制器(系统内部)
- 上位机软件                     - FreeRTOS 任务(系统内部)
- 云端服务器                     - 数据处理函数(系统内部)

判断口诀

Actor 一定在系统边界外部,不能是系统的组成部分。


2️⃣ 用例(Use Case)

定义

系统对 Actor 提供的一个完整的、有价值的功能。

📌 判断标准(非常重要)

一个合格的用例必须满足:

  1. Actor 能主动发起吗?

    • ✅ "用户登录系统"
    • ❌ "验证密码"(这是登录的一部分,不是独立用例)
  2. 功能是否对 Actor 有意义?

    • ✅ "查询温度数据"
    • ❌ "读取 ADC 寄存器"(这是实现细节)
  3. 是否是完整的交互?

    • ✅ "上传文件"(完整流程)
    • ❌ "打开文件对话框"(只是步骤)
用例命名规范
复制代码
✅ 好的命名(动宾结构)          ❌ 不好的命名
------------------------------------------------------
- 查询设备状态                   - 状态查询功能
- 配置通信参数                   - 参数配置
- 导出数据报表                   - 导出
- 接收传感器数据                 - 数据接收处理模块

命名原则

  • 动词开头,体现动作
  • 清晰表达用户意图
  • 避免技术术语

3️⃣ 系统边界(System Boundary)

定义

明确"系统管到哪儿为止",划分系统的职责范围。

为什么系统边界很重要?
复制代码
没有边界的问题:
- 责任不清:出了问题不知道归谁
- 接口混乱:不知道哪些功能需要提供
- 测试困难:不知道测什么
📌 实际例子

嵌入式数据采集系统

复制代码
┌─────────────────────────────────────────────┐
│          数据采集系统(系统边界)              │
│                                             │
│  [启动采集]  [停止采集]  [查询数据]         │
│  [配置参数]  [导出数据]                     │
│                                             │
└─────────────────────────────────────────────┘
     ↑             ↑              ↑
   用户          传感器         上位机

边界内:系统负责的功能
边界外:外部实体(Actor)

四、用例图的标准图形元素

基本元素表

元素 图形表示 含义 画法说明
Actor 小人图标 外部角色 位于系统边界外
Use Case 椭圆 功能 位于系统边界内
System Boundary 矩形框 系统范围 包含所有用例
Association 实线 使用关系 连接 Actor 和 Use Case
Include 虚线箭头 <<include>> 包含关系 从基用例指向被包含用例
Extend 虚线箭头 <<extend>> 扩展关系 从扩展用例指向基用例
Generalization 空心三角箭头 泛化关系 Actor 或 Use Case 的继承

五、高级关系:Include 和 Extend

1️⃣ <<include>> ------ 必须发生

定义

一个用例一定会包含另一个用例,被包含的用例是基用例的必要组成部分。

使用场景
  • 提取公共功能
  • 避免重复
  • 必选子功能
示例
复制代码
          ┌──────────────┐
          │   用户登录    │
          └──────┬───────┘
                 │
            <<include>>
                 ↓
          ┌──────────────┐
          │   验证权限    │
          └──────────────┘

解释:登录时必须验证权限,没有例外

实际案例

复制代码
[发送数据包]
    │
    ├──<<include>>──→ [数据校验]
    ├──<<include>>──→ [添加协议头]
    └──<<include>>──→ [发送到串口]

每次发送数据都必须执行这三个步骤

2️⃣ <<extend>> ------ 条件发生

定义

特定条件下才发生的扩展功能,基用例可以独立完成,扩展用例是可选的。

使用场景
  • 可选功能
  • 异常处理
  • 特殊情况
示例
复制代码
          ┌──────────────┐
    ┌─────│   查询数据    │
    │     └──────────────┘
    │           ↑
<<extend>>      (条件:查询结果为空)
    │
    └──→ ┌──────────────┐
         │  显示无数据   │
         └──────────────┘

解释:只有在查询结果为空时,才会触发"显示无数据"

实际案例

复制代码
[购买商品]
    ↑
    │ <<extend>> (条件:使用优惠券)
    │
[使用优惠券]

购买商品可以独立完成,使用优惠券是可选的

📌 Include vs Extend 对比

特性 Include Extend
发生时机 必然发生 条件发生
箭头方向 基用例 → 被包含用例 扩展用例 → 基用例
独立性 被包含用例不能单独存在 扩展用例可以单独存在
典型场景 公共功能提取 可选功能、异常处理

记忆口诀

  • Include :我包含你,你是我的一部分
  • Extend :我扩展你,我是可选的附加功能

六、用例图最常见的 5 个错误(避坑指南)

❌ 错误 1:把内部模块当 Actor

复制代码
❌ 错误示例:
┌─────────────┐
│   UART      │ ← 这是系统内部模块,不是 Actor
└─────────────┘
        ↓
   [发送数据]

✅ 正确做法:
┌─────────────┐
│  上位机软件  │ ← 这才是外部实体
└─────────────┘
        ↓
   [发送数据]

判断方法:问自己"这是系统的一部分吗?"


❌ 错误 2:把函数名直接当用例

复制代码
❌ 错误示例:
- HAL_UART_Receive_IT()  ← 这是函数名
- GPIO_WritePin()        ← 这是实现细节
- memcpy()              ← 这是底层操作

✅ 正确做法:
- 接收传感器数据        ← 从用户视角描述功能
- 控制设备开关
- 备份数据

原则:用例描述"做什么",不是"怎么做"。


❌ 错误 3:用例粒度太细

复制代码
❌ 粒度太细:
- 发送一个字节
- 读取寄存器
- 切换 LED 状态

✅ 合适粒度:
- 通过串口发送数据包
- 读取设备配置
- 指示系统运行状态

判断标准

  • 用例对 Actor 是否有独立价值?
  • 用户会单独发起这个操作吗?

❌ 错误 4:不画系统边界

复制代码
❌ 没有边界:
职责不清,不知道哪些是系统功能

✅ 画出边界:
┌───────────────────────────┐
│     智能温控系统          │ ← 明确系统范围
│  [监测温度]  [调节温度]   │
└───────────────────────────┘

重要性

  • 明确系统职责
  • 便于需求评审
  • 清晰的测试范围

❌ 错误 5:用例图里出现流程箭头

复制代码
❌ 错误示例(像流程图):
[登录] ──→ [验证] ──→ [进入系统]
   ↓
[失败] ──→ [提示错误]

✅ 正确示例(用例图):
┌──────────────────────┐
│    [用户登录]         │
│    [查看个人信息]     │
│    [修改密码]         │
└──────────────────────┘

记住

  • 用例图只表达"有哪些功能"
  • 不表达"先做什么后做什么"
  • 流程用活动图或时序图

七、完整示例:嵌入式数据采集系统

场景描述

一个通过串口与传感器通信的嵌入式数据采集系统。

用例图

复制代码
                    用户
                     │
        ┌────────────┼────────────┐
        │            │            │
        ↓            ↓            ↓
  ┌─────────┐  ┌─────────┐  ┌─────────┐
  │启动采集  │  │停止采集  │  │查询数据  │
  └─────────┘  └─────────┘  └────┬────┘
                                  │
                             <<include>>
                                  ↓
┌─────────────────────────────────────────────┐
│           数据采集系统                       │
│                                             │
│  ┌──────────┐         ┌──────────┐         │
│  │ 配置参数  │         │ 导出数据  │         │
│  └──────────┘         └──────────┘         │
│        ↑                                    │
│        │                                    │
│   <<extend>>                                  │
│  (参数异常)                                 │
│        │                                    │
│  ┌──────────┐                               │
│  │报警提示  │                               │
│  └──────────┘                               │
│                                             │
└─────────────────────────────────────────────┘
         ↑                          ↑
      传感器                      上位机

用例清单

用例名称 Actor 描述
启动采集 用户 开始从传感器采集数据
停止采集 用户 停止数据采集
查询数据 用户、上位机 查看已采集的数据
配置参数 用户 设置采样频率、阈值等
导出数据 用户 将数据导出为文件
报警提示 系统 参数异常时自动报警
上报数据 传感器 传感器主动推送数据

八、用例图的工程化实践建议

1. 什么时候画用例图?

复制代码
✅ 适合画用例图的场景:
- 项目启动,需求分析阶段
- 与客户/产品经理评审需求
- 系统功能清单不明确时
- 多方协作,需要统一认知

❌ 不适合画用例图的场景:
- 单纯的算法实现
- 内部模块设计(用类图)
- 详细流程设计(用活动图)

2. 用例图的详细程度

原则:不用追求完整,但一定要准确

复制代码
初期(需求讨论):
- 粗粒度用例
- 关注主要功能
- 5-10 个核心用例

中期(设计评审):
- 细化重点用例
- 补充 include/extend
- 15-20 个用例

后期(测试依据):
- 每个用例对应测试用例
- 补充异常场景

3. 用例描述模板

除了用例图,每个用例还应有文字描述:

markdown 复制代码
### 用例:查询设备数据

**ID**:UC-001
**Actor**:用户、上位机
**前置条件**:设备已连接,采集已启动
**主流程**:
1. Actor 发起查询请求
2. 系统验证权限
3. 系统返回最新数据
4. 系统记录查询日志

**后置条件**:数据已返回,日志已记录
**异常流程**:
- E1:权限不足 → 返回错误码
- E2:数据不存在 → 提示无数据

4. 与其他图的配合

复制代码
用例图(What)
    ↓
活动图(How - 流程)
    ↓
时序图(How - 交互)
    ↓
类图(Structure)
    ↓
代码(Implementation)

参考资源

  • UML 2.5 官方规范
  • 《UML 精粹》- Martin Fowler
  • 《面向对象分析与设计》- Grady Booch
  • 《敏捷软件开发》- Robert C. Martin

记住用例图是需求和设计的桥梁,画好用例图是软件工程的基本功!

相关推荐
wdfk_prog2 小时前
[Linux]学习笔记系列 -- [fs][fs_parser]
linux·笔记·学习
白帽子凯哥哥2 小时前
在学习SQL注入或XSS这类具体漏洞时,如何设计一个高效的“理论+实践”学习循环?
sql·学习·漏洞·xss
zhaodiandiandian3 小时前
AI智能体重构产业生态,从效率革命到体验升级
人工智能·microsoft
独自归家的兔3 小时前
开发核心问题深度解析:通配符接口 + 第三方数据同步 + 九宫格算法
服务器·windows·microsoft
全栈陈序员3 小时前
v-if 和 v-for 的优先级是什么?
前端·javascript·vue.js·学习·前端框架·ecmascript
全栈陈序员3 小时前
你对 SPA 单页面应用的理解?它的优缺点分别是什么?如何实现 SPA 应用?
前端·vue.js·学习·前端框架·vue
许泽宇的技术分享3 小时前
当AI Agent学会“打电话“——微软Agent Framework的A2A与AGUI协议深度解析
人工智能·microsoft·a2a协议·ai多智能体·agui
soumns丶涛3 小时前
ESP32学习(1) - 点亮第一个LED
学习
全栈陈序员3 小时前
请描述下你对 Vue 生命周期的理解?在 `created` 和 `mounted` 中请求数据有什么区别?
前端·javascript·vue.js·学习·前端框架