在领域驱动设计中,消息总线服务位于哪里?

8
我希望能够进一步了解领域驱动设计(DDD),更具体地说,如何通过消息总线处理领域事件以进行异步处理。
假设我有一些架构 ->
 _____________________
|                     |
|        Client       |
|_____________________|
           |
 __________|__________
|                     |
| Application Service |
|_____________________|
           |
 __________|__________
|                     |
|        Domain       |
|_____________________|

当我的域引发一些域事件时,我该如何将该事件传递到消息服务(例如RabbitMQ)中?
我的第一个想法是注入一个消息总线服务 IMessageBus,它知道如何将事件发送到 RabbitMQ。该服务将被领域事件处理程序用于将事件分派到总线上。
但是我又想到了,现在我的领域必须知道如何处理自己的事件。
有人能够阐明这个问题吗?
2个回答

6
服务总线是基础设施的一部分,但应用程序服务知道它(作为抽象)。将总线注入应用程序服务是可以的,因为应用程序服务不包含领域逻辑,而是充当业务用例的协调器和主机。
但是我想,现在我的领域必须知道如何处理自己的事件了。
是的,但总线只传递消息,消息处理程序基本上是应用程序服务。
Rabbit和其他实现细节,你的应用程序处理程序应该由服务总线调用(应该抽象出实际的消息处理过程)。

总线的抽象在哪里?所有的抽象都存在于领域中,即使只在应用层中使用的抽象也是如此吗?我猜这可能是情况,因为您永远不知道逻辑何时会移动到领域服务中。 - plalx
总线的抽象是总线定义的一部分。应用程序服务将其用作外部服务。这里的重要点是,应用程序服务是一个域门面,因此并不真正属于域本身。如果您在域内定义应用程序服务,则存储库接口之类的内容也是其中的一部分,但仅作为技术细节。但是,总线抽象不应该是域甚至应用程序本身的一部分。毕竟,服务总线是您的应用程序使用的独立组件。 - MikeSW
我不确定我是否正确理解了你的解释。通过抽象,我基本上是指接口。通常,您会在域中声明接口,例如存储库接口,并在基础结构层中实现它们。应用程序层将依赖于接口,除了组合根还必须依赖于基础结构层。现在,这是有道理的,因为存储库接口可能会从域服务中使用。因此,我们也应该在域中声明消息总线接口吗? - plalx
1
不应该在域服务中使用外部服务,它的工作是封装特定的域行为(而不是查询数据或与非域项通信)。只有应用程序服务应该知道/处理诸如存储库或服务总线之类的事情,即使它们只是抽象。您在域中拥有“IRepository”的原因是因为您不希望应用程序的其他部分(除了持久性实现)直接访问业务对象。但是,总线仅关心本质上是DTO的消息。 - MikeSW
我认为“抽象存在的位置”这个问题旨在询问实体如何获取总线的引用以发送事件。这类似于存储库。像IRepository这样的接口应该是域层的一部分。如果它存在于应用程序层,则域实体无法触发事件或处理它们。这些接口是依赖反转原则和Martin Fowler的插件模式的案例。 - DanielB

2
这个问题类似于“您的域如何与外部系统(除数据持久性之外)通信?”服务总线与物理传感器或其他外部硬件没有什么不同。通常,人们会将这些物理事物在代码中表示为抽象物理概念的对象。它们位于问题域(PD)之外,可以被视为系统集成(SI)对象。如果您的域需要与外部系统通信,则只需调用其等效的SI对象即可。同样,SI对象也可以调用您的域。注意:此答案假定您的域不是贫血的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接