Extend用于向另一个一级用例添加步骤。
例如,想象一下“取款”是自动柜员机(ATM)的一个用例。 "收费"将扩展"取款"并描述当ATM用户没有在ATM所属机构开户时实例化的条件“扩展点”。请注意,基本的“取款”用例可以独立存在,没有这个扩展。
Include用于提取在多个用例中重复的用例片段。被包含的用例不能独立存在,原始用例没有包含的用例是不完整的。应该节俭地使用,并且仅在重复是显著的且是有意设计的情况下使用(而不是巧合的情况)。
例如,每个ATM用例开始时发生的事件流程(用户插入ATM卡,输入密码,显示主菜单)将成为包含的良好候选。
这可能会引发争议,但“包含(includes)总是,扩展(extends)有时”是一个非常常见的误解,几乎已经成为事实上的含义。以下是一种正确的方法(在我的观点下,并经过了Jacobson、Fowler、Larmen和其他10个参考文献的核对)。
理解使用案例之间的包含和扩展关系的关键在于意识到,与UML的其余部分相同,使用案例之间的虚线箭头表示依赖关系。我将使用“基础”、“包含”和“扩展”这些术语来指代使用案例角色。
基础使用案例依赖于包含的使用案例;如果没有它/它们,基础使用案例就不完整,因为包含的使用案例代表可能始终或有时发生的交互子序列。(这与一个流行的误解相矛盾,即您的使用案例中所提供的主要情景永远发生在主流程中,有时发生在备选流程中,这只取决于您选择的主要情景;使用案例可以很容易地重构为表示不同的流程作为主要情景,这应该无关紧要。)
在单向依赖的最佳实践中,基础使用案例了解(并引用)包含的使用案例,但包含的使用案例不应“知道”基础使用案例。这就是为什么包含的使用案例可以是:a)它们自己的基础使用案例;b)多个基础使用案例共享的原因。
扩展的使用案例依赖于基础使用案例;它实际上扩展了基础使用案例所描述的行为。基础使用案例应该是一个完全功能的使用案例(当然包括了包含的使用案例),没有扩展使用案例的额外功能也可以正常运行。
扩展使用案例可用于几种情况:
需要考虑的一个重要方面是,扩展用例可以在基本用例的流程中的多个位置“插入”行为,而不仅仅是像包含用例一样在单个位置上。因此,几乎不可能使用扩展用例来扩展多个基本用例。
至于依赖性,扩展用例依赖于基本用例,并且再次是单向依赖,即基本用例在序列中不需要引用扩展用例。这并不意味着你不能演示扩展点或将对扩展用例的交叉引用添加到模板的其他位置,但是基本用例必须能够在没有扩展用例的情况下工作。
我希望我已经表明,“包括始终,扩展有时”的普遍误解是错误的或者最多只是简单化了。如果你考虑有关箭头方向性的所有问题,这个版本实际上更有意义-在正确的模型中,它只是依赖关系,如果你重构用例内容,它不会潜在地改变。
我经常使用这个来记住这两个要点:
我的使用场景: 我要去城市。
包括 -> 驾驶汽车
扩展 -> 加油
"加油"可能并不总是必要的,但根据汽车中还剩多少汽油可以选择性地进行。"驾驶汽车"是前提条件,因此我将其包含在内。
用例用于记录行为,例如回答这个问题。
如果一个行为是在另一个行为的基础上增加的,但不一定是该行为的一部分,则称之为扩展,例如研究答案。
还要注意,如果您不打算回答这个问题,研究答案就没有意义。
如果一个行为是包含在另一个行为中的一部分,则称为包含,例如登录到Stack Exchange。
需要澄清的是,这个图示仅在您想在Stack Overflow这里回答问题时才是真实的。:)
这些是来自UML 2.5页面671-672的技术定义。
我强调了我认为重要的点。
扩展
扩展是从扩展用例(扩展)到被扩展用例(被扩展案例)的关系,指定了在何时以及如何将定义在扩展用例中的行为插入到被扩展用例中定义的行为中。 扩展发生在被扩展用例中定义的一个或多个特定扩展点上。
当需要添加一些额外的行为可能是有条件的,Extend 被设计用于此目的。
扩展用例是独立于被扩展的用例定义的,并且在不考虑被扩展的用例时也具有意义。另一方面,扩展用例通常定义了在本身情况下可能并没有意义的行为。 相反,扩展用例定义了一组模块化的行为增量,在特定条件下增强了被扩展用例的执行。
...
包含
包含是两个用例之间的DirectedRelationship,表示包含使用案例(附加部分)被插入到包含使用案例(包含用例)的行为中。它也是一种NamedElement,因此在其所属的UseCase(包含用例)上下文中可以有一个名称。包含用例可能依赖于执行包含用例产生的更改。为了完整描述包含用例的行为,必须可用包含用例的行为。
包含关系旨在用于两个或多个使用案例的行为存在共同部分的情况。然后将这个公共部分提取到一个单独的使用案例中,以便所有具有这个公共部分的基础使用案例都可以包含它。由于包含关系的主要用途是重用公共部分,所以留在基础使用案例中的内容通常本身并不完整,而是依赖于包含部分才能有意义。这反映在关系的方向上,表示基础使用案例依赖于附加部分但反之则不然。
...
include
:
extend
:
我认为理解包含和扩展的意图非常重要:
"包含关系旨在通过另一个用例建模并重用行为,而扩展关系旨在添加现有用例的部分以及建模可选系统服务" (Overgaard和Palmkvist,《用例:模式和蓝图》Addison-Wesley, 2004)。
我认为这个意思是:
包含 = 功能的重用(即包含的功能在系统中被使用或可能被使用)。因此,包含表示对另一个用例的依赖性。
扩展 = 添加(而不是重用)功能和任何可选功能。因此,扩展可以表示两种情况:
1、向用例添加新的特性/功能(可选或不可选)
2、任何可选用例(现有的或不现有的)。
总结:
包含 = 功能的重用
扩展 = 新的和/或可选的功能
你最常见到扩展的第二种用法(即可选功能),因为如果功能不是可选的,那么大多数情况下它会内置到用例本身中,而不是作为扩展。至少这是我的经验。(Julian C指出,在项目进入第二阶段时,有时会看到扩展的第一种用法(即添加新功能)。
我认为MSDN在这里所解释的内容相当易于理解。
包含 [5]
包含用例调用或调用被包含的用例。包含用于显示用例如何分解为更小的步骤。被包含的用例位于箭头末端。
扩展 [6]
与此同时,扩展用例向扩展的用例添加目标和步骤。扩展仅在特定条件下运行。被扩展的用例位于箭头末端。
让我们更清晰地解释一下。每当我们想表达一个情况的存在取决于另一个情况的存在时,就使用include
。
例子:
用户只有在登录账户后才能在线购物。换句话说,在他登录账户之前,他不能进行任何购物。
在素材上传之前,用户无法从网站上下载。因此,如果没有上传任何内容,我不能下载。
你明白了吗?
这是关于条件结果的。如果之前我没有做某事,那么我就不能做这件事。
至少,我认为上面关于笔记本电脑和保修的例子是最有说服力的!
<include>
和 <extend>
都依赖于基类,但是<extend>
是可选的,也就是说它是从基类派生出来的,但从用户的角度来看,它可以使用或者不使用。
<include>
被纳入到基类中,也就是说在您的用例中使用<include>
是强制性的,否则会被视为不完整。<extend>
,因为这取决于用户是否要取款、存款或查询,这些都是可选的。<include>
,因为用户必须插入一张卡片并输入有效的密码进行验证。