大部分人画的用例图,其实不是用例图,是一张功能菜单。
登录、注册、查询、导出、管理用户……十个椭圆围一个小人,画完自己都觉得没用。
先说一个反常识的结论:用例图不是"系统有什么功能",是"谁要什么,系统答应给他什么"——它是一份范围契约,不是一份清单。
这篇文章把这张图讲透:怎么定颗粒度、include 和 extend 到底谁指向谁,以及一个从 34 个功能点收敛到 11 个用例的完整算例。
一、判断用例颗粒度的唯一标准
一句话:一次交互,能不能给参与者一个完整的价值?
- "点击查询按钮"不是用例,它只是一个动作
- "查询本月报销记录"才是用例,因为查完这件事就结束了,用户拿到了他要的东西
再粗暴一点的测试:做完这件事,用户能不能说一句"好了"。说不出来,就是没画完。
一点五、参与者怎么找:问业务三个问题
找参与者不要凭空想,拿这三个问题去问业务:
- 谁会主动用这个系统(主要参与者)?
- 谁会收到它的东西,或者给它东西(次要参与者、外部系统)?
- 谁来维护它、配置它(后台参与者)?
第三个最容易被忘。管理员这个小人一漏,后台配置的工作量就没人估,经常到上线前三天才发现规则还没有配置入口。
外部系统也有个笨办法:拿定时、回调、推送、同步这四个词,在需求文档里搜一遍,每个命中后面大概率藏着一个外部参与者。我们就是用这个办法,在报销系统里挖出了三个:OA 推待办、银行回写、财务月度对账。

二、三件套,以及那条最容易画反的线
| 元素 | 画法 | 一句话说明 |
|---|---|---|
| 参与者 | 小人 | 系统之外的人或系统,不是"用户"两个字 |
| 用例 | 椭圆 | 一次能交付完整价值的交互 |
| 系统边界 | 矩形框 | 框内是你要做的,框外不是 |
| 关联 | 实线 | 参与者参与了这个用例 |
| 包含 include | 虚线 + <> | 必须走的那一步,箭头指向被包含用例 |
| 扩展 extend | 虚线 + <> | 可选的那一步,箭头从扩展用例指向基础用例 |
记忆口诀只有一句:include 指向被包含,extend 从扩展指回基础。
为什么 extend 是反着指的?因为扩展是"加戏"——它知道自己在给谁加戏(所以箭头指向基础用例),而基础用例并不知道自己会被谁加戏(它不该依赖扩展)。这条线画对了,你的代码里就不会出现"基础流程里写着一堆 if 判断特殊场景"的烂摊子。
三、完整算例:一个内网报销审批系统
3.1 先收敛范围
需求文档里一共列了 34 个"功能点"。按上面的标准过一遍,砍掉 23 个(按钮级、页面级、纯配置项),剩下 11 个用例。
收敛的方法很机械,但有效:把 34 个功能点逐个问一句"做完用户能说好了吗"。按钮级的(导出表格、翻页、排序)合并进它的宿主用例;纯配置项(字典、开关)合并进配置审批规则;只有能交付一次完整价值的,才留下来。
| 用例 | 发起者 | 说明 |
|---|---|---|
| 提交报销 | 员工 | 含票据上传 |
| 查看我的报销 | 员工 | 列表 + 详情 |
| 撤回申请 | 员工 | 仅审批前 |
| 审批报销 | 部门主管 | 通过 / 驳回 |
| 财务复核 | 财务 | 抽查 + 打款 |
| 导出报销台账 | 财务 | 月度对账 |
| 配置审批规则 | 管理员 | 金额阈值 |
| 管理组织架构 | 管理员 | 部门与汇报关系 |
| 查看统计报表 | 主管 / 财务 | 部门花费 |
| 接收 OA 待办 | OA 系统(外部参与者) | 推送待办 |
| 同步打款结果 | 银行系统(外部参与者) | 回写状态 |
这个过程最实在的收益:评审会从 90 分钟压到 35 分钟。因为大家终于在讨论"做什么",而不是"第 17 个按钮放哪儿"。
3.2 include 和 extend 分别用在哪
以"提交报销"这个用例为例:
- include「校验票据」:提交报销 →(include)→ 校验票据。每次提交都必须走,不走就提交不了,所以是包含。
- include「计算金额」:同理,必须算。
- extend「超预算需上级审批」:提交报销 ←(extend)— 超预算需上级审批。守卫条件是
[金额 > 2000]。
业务数据是这样的:这个系统月均报销单 1.2 万单,其中超过 2000 元的占 61%——也就是说,61% 的单子会触发扩展路径,39% 的单子走基础路径。
这就是为什么它必须是 extend 而不是写死在主流程里:阈值会变(去年是 2000,前年是 1000),写法不同的话,每次调阈值都要动主流程,回归测试要跑一遍全量。
顺带说一句验收标准:extend 的守卫必须写成可判断的。写"大额"是废话,写"金额大于 2000"才是规则。评审时逐条念守卫,念不出具体数值或具体条件的,说明业务规则还没定,先别画那条线。

3.3 别忘了框外的两个小人
最后两个用例的参与者是系统,不是人:OA 系统推待办、银行回写打款结果。
外部系统是最常被漏掉的参与者。 漏掉它的后果很具体:上线后才发现"待办推不过去",而这个接口的工作量没人估过。
四、画用例图的 5 个坑
- 把用例画成功能菜单。判断标准就是前面那句"能不能说一句好了"。
- 参与者笼统写成"用户"。写"用户"说明你没想清楚角色——员工和主管在这个系统里的权限完全不同,画成一个小人,后面所有权限设计都会跟着错。
- include 和 extend 箭头画反。再念一遍口诀:include 指向被包含,extend 从扩展指回基础。
一个简单的验收办法:把图给开发看,让他指着自己代码里的 if-else 说"这是 extend"。对不上,就是画反了。
4. 不画系统边界框。没有框,就分不清哪些是你这次要做的,哪些是别人的系统。范围永远是需求会上吵架的第一原因。
最后给一句实在话:用例图是这几张图里最便宜的一张,画一张不到半小时。但它省下的返工,往往以周计算——范围错了,后面画得再漂亮,都是在给错误加速。
5. 用例之间画箭头。用例之间不存在"顺序"关系,那是时序图和活动图的事。用例之间只有 include、extend、泛化三种,别的线都是错的。
四点五、每个用例配一段四行描述
图上只有名字是不够的。每个用例背后还应该配四行,写进文档:
- 谁发起
- 前置条件(在什么状态下才能做)
- 主流程(几步,每步一句话)
- 异常流程(失败了怎么办)
这四行写完,用例图才算从示意图变成能干活的东西。我们组的经验:11 个用例,四行模板写完一共两页纸,评审会上再没人问"这个到底要做到哪一步"。
五、画完自检的 9 条
- 每个用例都能让参与者说一句"好了"吗?
- 参与者写的是角色还是"用户"两个字?
- 系统边界框画了吗?框外的东西明确吗?
- 外部系统参与者列全了吗(含定时任务、消息回调)?
- include 的箭头指向被包含用例了吗?
- extend 的箭头从扩展指回基础了吗?守卫条件写了吗?
- 有没有两个用例在做同一件事(重复)?
- 每个用例都有明确的发起者吗(找不到发起者的用例,通常是不该做的)?
- 和最核心的那个参与者的用例,能在十分钟内讲给业务听懂吗?
六、和系列其他图怎么分工
| 你想说清的事 | 该画哪张图 |
|---|---|
| 系统要做什么、给谁做(范围) | 用例图(本文) |
| 有什么、由什么组成(结构) | 类图(Day45) |
| 存什么、怎么关联(数据) | ER 图(Day50) |
| 一次交互怎么协作(顺序) | 时序图(Day51) |
| 一个对象的一生(状态) | 状态图(Day51) |
口诀:用例图定范围,时序图定顺序,状态图定生死,ER 图定存储。
开工顺序也建议照这个来:先画用例图把范围定死,再往下画。很多项目返工,不是因为图画得丑,是因为范围从第一天起就没说过清楚。
关键词:用例图、UML 用例图、use case diagram、include 与 extend 区别、系统边界、参与者 actor、需求分析
