在用例图中包含和扩展之间的区别是什么?


当前回答

还要注意UML版本:现在<<使用>>和<<包含>>已经很长时间了,已经被<<包括>>所取代,<<扩展>>由<<扩展>>和泛化。 对我来说,这往往是误导性的观点:例如Stephanie的帖子和链接是关于一个旧版本的:

在付款时,您可以选择货到付款、使用paypal付款或刷卡付款。这些都是“为物品付费”用例的替代方案。我可以根据自己的喜好选择其中任何一种。

事实上,除了“为物品付费”,没有其他选择!在现在的UML中,“货到付款”是一个扩展,“使用paypal支付”/“刷卡支付”是专门化的。

其他回答

为了简化,

为包括

当基本用例执行时,包含的用例将每次执行一次。 基本用例需要完成所包含的用例才能完成。

一个典型的例子:在登录和验证密码之间

(登录)——<< include >>——>(验证密码)

为了使登录过程成功,“验证密码”也必须成功。


为扩展

当基本用例被执行时,扩展用例只是偶尔执行 扩展用例仅在满足某些条件时才会发生。

一个典型的例子:在登录和显示错误消息之间(只偶尔发生)

(登录 ) <--- << 扩展> >——(显示错误消息)

“show error message”只在登录过程失败时才会出现。

当用例向另一个一级用例添加步骤时,使用Extend。

例如,假设“提取现金”是自动柜员机(ATM)的一个用例。“评估费用”将扩展提现并描述有条件的“扩展点”,该“扩展点”在ATM用户不在ATM所属机构存入银行时实例化。注意,基本的“Withdraw Cash”用例独立存在,没有扩展。

Include用于提取在多个用例中重复的用例片段。被包含的用例不能独立存在,没有被包含的用例原始的用例是不完整的。这应该谨慎使用,并且只在重复很明显并且是故意存在(而不是巧合)的情况下使用。

例如,在每个ATM用例开始时发生的事件流(当用户放入他们的ATM卡,输入他们的PIN,并显示主菜单时)将是一个很好的包含候选。

这可能会引起争议,但“包含总是,扩展有时是”是一个非常常见的误解,现在几乎已经取代了事实上的含义。以下是一个正确的方法(在我看来,并与雅各布森、福勒、拉尔曼和其他10个参考文献进行了对比)。

关系是依赖关系

包含和扩展用例关系的关键是要认识到,与UML的其余部分一样,用例之间的虚线箭头是一种依赖关系。我将使用术语“基本”、“包含”和“扩展”来指代用例角色。

包括

A base use case is dependent on the included use case(s); without it/them the base use case is incomplete as the included use case(s) represent sub-sequences of the interaction that may happen always OR sometimes. (This is contrary to a popular misconception about this, what your use case suggests always happens in the main scenario and sometimes happens in alternate flows simply depends on what you choose as your main scenario; use cases can easily be restructured to represent a different flow as the main scenario and this should not matter).

在单向依赖的最佳实践中,基本用例知道(并引用)被包含的用例,但被包含的用例不应该“知道”基本用例。这就是为什么包含的用例可以是:a)它们自己的基本用例和b)由许多基本用例共享。

扩展

扩展用例依赖于基本用例;它从字面上扩展了基本用例所描述的行为。基本用例本身应该是一个完全功能的用例(当然包括了),没有扩展用例的附加功能。

扩展用例可以在以下几种情况下使用:

The base use case represents the “must have” functionality of a project while the extending use case represents optional (should/could/want) behavior. This is where the term optional is relevant – optional whether to build/deliver rather than optional whether it sometimes runs as part of the base use case sequence. In phase 1 you can deliver the base use case which meets the requirements at that point, and phase 2 will add additional functionality described by the extending use case. This can contain sequences that are always or sometimes performed after phase 2 is delivered (again contrary to popular misconception). It can be used to extract out subsequences of the base use case, especially when they represent ‘exceptional’ complex behavior with its own alternative flows.

需要考虑的一个重要方面是,扩展用例可以在基本用例流中的几个地方“插入”行为,而不是像被包含的用例那样只在一个地方插入。由于这个原因,扩展用例不太可能适合扩展多个基本用例。

至于依赖关系,扩展用例依赖于基本用例,同样是单向依赖,即基本用例不需要序列中任何对扩展用例的引用。这并不意味着您不能演示扩展点或在模板的其他地方向扩展用例添加x-ref,而是基本用例必须能够在没有扩展用例的情况下工作。

总结

我希望我已经说明了“包含总是,扩展有时是”的常见误解要么是错误的,要么充其量是简单的。如果你考虑到误解所呈现的箭头方向的所有问题,这个版本实际上更有意义——在正确的模型中,它只是依赖关系,如果你重构用例内容,它不会潜在地改变。

<include>和<extend>都依赖于基类,但<extend>是可选的,也就是说,它是从基类派生的,但在用户的角度来看,它可以被使用,也可以不被使用。

<include>被合并到基类中,也就是说,在用例中必须使用<include>,否则它将被认为是不完整的。

eg:

在ATM机构造上(根据用户角度):

1:提现、存现、支票账户属于<extend>,因为它取决于用户是提现、存款还是支票。这些都是用户可以选择做的事情。

2:“输入pin,放置卡片,移除卡片”这些是在<包括>下的事情,因为用户必须,而且应该,放置卡片并输入有效的pin进行验证。

这里已经解释了两者之间的区别。但没有解释的是,<<include>>和<<extend>>根本不应该被使用。

如果你读过Bittner/Spence,你就知道用例是关于综合的,而不是分析的。用例的重用是毫无意义的。它清楚地表明您已经错误地切割了您的域名。附加值本身必须是唯一的。我所知道的唯一附加值再利用方式就是特许经营。如果你是做汉堡生意的,很好。但在其他任何地方,你作为BA的任务是试图找到一个USP。这必须在良好的用例中呈现。

每当我看到人们使用其中一种关系时,都是在尝试进行功能分解的时候。这是完全错误的。

简单地说:如果你可以毫不犹豫地回答你的老板“我做了……”,那么“……”就是你的用例,因为你这样做得到了钱。(这也清楚地表明“登录”根本不是一个用例。)

在这方面,找到包含或扩展其他用例的独立用例是非常不可能的。最终,您可以使用<<extend>>来显示您的系统的可选性,即一些许可模式,它允许包含某些许可的用例或省略它们。但除此之外,就避免他们。