【问题标题】:Inject EventDispatcher into an Entity in a DDD way以 DDD 方式将 EventDispatcher 注入到实体中
【发布时间】:2015-08-04 15:32:57
【问题描述】:

以 DDD 方式将 EventDispatcher 注入实体是否正确?

假设我有一个名为 Card 的 DomainModel。这张通用语言的卡可以激活和停用。但是激活和停用涉及调用它在现实世界中激活的第三方 API。

所以为了保持我们的领域模型清晰,我的方法是我的 Card 实体有一个如下所示的激活方法:

public function activate()
{
    $this->active = true;

    $this->dispatcher->dispatch(CardEvents::CARD_ACTIVATION, new CardActivation($this));
}

然后服务正在侦听调度程序以使用外部 API 激活或不激活。

将这个 EventDispatcher 注入到实体中是否正确?

如果调用api失败怎么办?

有没有感觉监听服务最终改变了 Card 本身的 active 属性?

谢谢。

【问题讨论】:

  • 你可以依赖一个简单的同步事件分派器(没有成熟的消息机制)作为一个静态类。您可以在域实体中执行类似DomainEvents.raise(...) 的操作。由于事件将被同步处理,因此将在同一事务中处理。另一种解决方案是将ICardActivator 传递给activate 函数,例如card.activate(activator)。最后,您也可以只调用应用层中的服务。 card.activate(); cardService.activate(card);.
  • 有些人还会在实体中记录事件,存储库或应用程序服务将负责发布它们。

标签: service domain-driven-design event-dispatching


【解决方案1】:

如果 activate 方法中的这个 EventDispatcher 只是对来自域的接口的引用,那么是的,没关系。然后,您可以将此接口从您的域公开到另一层并创建一个实现该接口的类(例如在应用程序层中),并且可以使用第三方库或其他任何东西来实现该类。这样一来,您的域就不会知道IEventDispatcher 接口是如何实现的,从而确保它不会被更改。

请记住,更改此 EventDispatcher 的实现方式(如果它使用第三方插件,或者如果您自己实现)不应影响您的域/业务逻辑。也许使用它的应用程序可能会受到影响。您可能有许多应用程序(Web、移动、桌面)可以停用卡片,每个应用程序都有不同的 EventDispatcher 版本/实现(或相同),这不会影响您的域。如果是这样,那么您应该检查您的设计。

此外,只有当您必须调用 EventDispatcher 时,我才会将 EventDispatcher 保留在您的 Card 模型中,无论哪个应用程序(Web、桌面、移动、Web 服务)请求 activate() 方法,这意味着调用 dispatch() 方法some EventDispatcher 是您的业务逻辑的一部分(请注意对 some 词的强调,因为域不知道它是如何实现的,它),只是因为您的域希望给应用程序一个执行 dispatch 的机会,无论它是否有效,无论它是否执行某些操作(域不关心它,它只是调用它)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-27
    • 2018-02-28
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    相关资源
    最近更新 更多