用例图栏目 ·

include 和 extend 的区别:什么时候用包含,什么时候用扩展(附反例)

一篇讲清 UML 用例图中 include 与 extend 的区别与判断规则:什么时候该用包含、什么时候该用扩展、方向怎么画、常见反例与替代画法。

很多人第一次画用例图时,最容易卡在两条关系上:include(包含)extend(扩展)。它们看起来都像“一个用例连到另一个用例”,但背后的含义完全不同。

如果你现在的困惑是下面这些,往下看就能对上号:

  • 这个步骤是“必须发生”的,还是“有条件才发生”的?
  • 箭头到底指向谁?为什么我画出来总被说反了?
  • 我把“登录”画成 extend 合不合适?把“校验输入”画成 include 对不对?

下面用一套可落地的判断规则讲清楚差别,并给你一些常见反例,避免“画得像、意思不对”。

先给结论:一句话区分 include 与 extend

  • include:把“必做的公共步骤”抽出来复用。A include B 表示:执行 A 时,一定会执行 B(至少在语义上是必需的)。
  • extend:把“可选/条件触发的分支”挂上去。A extend B 表示:在某些条件下,会在 B 的某个点插入 A;不触发条件时,B 仍然成立。

很多误用都来自把“复用”当成唯一动机。实际上:

  • include 的核心是 必需性(mandatory) + 共用子流程(shared sub-flow)
  • extend 的核心是 条件性(conditional) + 对基础用例的非侵入扩展(base still valid)

判断规则(建议你直接背下来)

你只要按顺序问三个问题,基本不会错。

规则 1:不执行 B,A 还能算“完成”吗?

  • 不能完成 → 倾向 include(B 是 A 的必备子流程)
  • 仍能完成 → 不要用 include,继续看规则 2

例子:

  • “下单”若不“计算订单金额/校验库存”,就不能算完成 → 更像 include
  • “浏览商品”即使不“加入收藏”,仍是完成的 → 不该 include

规则 2:A 是否是对 B 的“可选加料”,而不是 B 的必要步骤?

  • 是可选加料/条件触发 → 倾向 extend
  • 不是 → 继续看规则 3

例子:

  • “使用优惠券”是对“结算”的可选加料:不用券也能结算 → extend
  • “二次验证(MFA)”对“登录”是否可选,要看业务:
    • 若对所有用户必需 → include(或直接作为登录的主流程步骤)
    • 只对高风险登录触发 → extend(更贴近条件分支)

规则 3:你是为了“复用文字”,还是为了表达“需求逻辑”?

如果只是为了让图更短、避免重复写几步,但那些步骤并不独立,也不需要复用给多个用例,可以不拆

  • 用例图的目标是表达参与者与系统的交互目标,不是把每个 UI 操作都拆成一个用例。
  • 过度拆分往往会把 include/extend 用成“抽函数”,图反而更乱。

箭头方向怎么画(最容易画反的点)

先说结论(按常见 UML 画法):

  • include:箭头从“包含者”指向“被包含者”
    • A —<>—> B
    • 读法:A 包含 B
  • extend:箭头从“扩展用例”指向“被扩展(基础)用例”
    • A —<>—> B
    • 读法:A 扩展 B

你可以用一句话记:

  • include:A “用到了” B,所以指向被用到的 B
  • extend:A “挂到” B 上,所以指向被挂的 B(B 是基础)

什么时候更适合用 include

下面这些场景,用 include 通常比较自然:

1) 多个用例都必须做同一段子流程

例:

  • “下单”与“修改订单”都必须“校验库存”
  • “注册”与“找回密码”都必须“发送验证码”

注意:必须 是关键。

2) 你想表达“基础能力被反复调用”

比如“身份校验/权限校验/格式校验”这种横切能力,如果确实是多个业务用例的必经步骤,抽成 include 能让图更清楚。

什么时候更适合用 extend

1) 只在某些条件下发生的分支

例:

  • “风控校验”只在高风险订单触发(扩展“提交订单”)
  • “人工审核”只在命中规则时触发(扩展“发起提现吗/开通权限”等)

2) 对基础用例的可选增值

例:

  • “开具发票”扩展“支付完成”(不开发票也能完成支付)
  • “加入收藏”扩展“浏览商品详情”(不收藏也能浏览)

这里的关键是:基础用例不被破坏,扩展只是加了一个可选动作。

5 个常见反例(以及更好的画法)

反例 1:把“登录”当成所有功能的 include

很多图会出现:下单 include 登录、发表评论 include 登录、查看订单 include 登录……

问题:

  • “登录”更像一个前置条件参与者状态,而不是每个业务目标都必须“调用一次登录用例”。

更常见的替代:

  • 在用例说明里写前置条件:“用户已登录”
  • 或者单独画一个“认证/会话管理”相关的用例,但不要到处 include

反例 2:把“异常处理”用 include 表达

比如“支付失败”被画成结算 include 支付失败。

问题:

  • include 表达的是“必发生的子流程”,异常显然不是。

更好的画法:

  • 用 extend 表达失败分支(在某条件下扩展基础流程)
  • 或在用例说明里把异常流写出来

反例 3:把“输入校验”用 extend 表达

例如“校验手机号” extend “注册”。

问题:

  • 大多数情况下校验是注册的必需步骤,不应是可选扩展。

更好的画法:

  • 直接把校验作为注册主流程的一部分
  • 或者多个用例共享且必需时,用 include 抽成子用例

反例 4:extend 被用成“继承/泛化”的替代

有些人会用 extend 表达“管理员功能包含普通用户功能”。

问题:

  • 这是**角色/用例泛化(generalization)**更合适,extend 不是继承。

更好的画法:

  • 对参与者用泛化:管理员 → 普通用户
  • 对用例也可用泛化表达“更具体的用例”

反例 5:为了复用一句话,把所有小步骤都拆成 include

比如“点击按钮”“填写表单”“保存”都拆成用例。

问题:

  • 用例应当是“用户目标”,不是 UI 原子操作。

更好的画法:

  • 合并成更有意义的用例(例如“提交申请”“更新资料”)
  • 把 UI 步骤放到用例说明或原型里

快速自检清单(画完 30 秒检查)

画完后,你可以用这份清单快速扫一遍:

  • include 目标是否真的是“必发生”?(不做就无法完成基础用例)
  • extend 是否真的是“可选/条件触发”?(不触发也不影响基础用例成立)
  • 箭头方向是否一致:include 指向被包含;extend 指向基础用例
  • 是否出现“把登录到处 include”“把异常用 include”的常见坑

需要一个可直接套用的模板?

如果你想把你的业务需求(参与者、目标、前置条件、可选分支)快速整理成一张用例图,可以用这个页面把信息填进去,然后导出图再微调:

如果你已经有一段需求描述(比如 PRD 里的流程、或一段“用户要做什么”的文字),也可以先把描述整理成要点,再用同一个入口生成一个初稿作为参考: