DDD:阻止外部服务调用和事件

DDD: Blocking External Service Calls and Events

我一直在寻找将外部服务集成到我的域中的最佳方法。

有很多第三方服务可以使用,所以我们有一个提供通用接口的适配器。我们在任何时候只有 X 个可用的服务实例(创建和销毁它们的成本很高),因此它们是从池中检索的。

外部服务被用作长 [​​=43=] 过程的一部分。该流程将由流程管理器实施。一个实体被调度,然后它向对象池请求资源,当资源空闲时它执行一个动作,然后记录结果,并将资源返回到池中。此过程的两个部分(请求空闲资源和执行操作)可能需要一些时间并且会阻塞调用。所以理想情况下,这些应该异步完成?

这意味着外部服务需要在资源空闲时以及计算出操作结果时引发事件。我看到的每个示例都提供了有关从聚合引发事件的指导。当外部系统(在本例中是通用子域?)需要报告事件时很少......所以我的问题:

我一直在努力寻找关于上述内容的具体指导,因此不胜感激。

在做一些进一步的研究之后,我将尝试回答我自己的问题。

My understanding is that any external service is basically a separate bounded context. In which case the Adapter and Pool are basically functioning as an ACL, by hiding the service behind a common interface. Is this assumption correct?

是的。一切都与语言有关。显然,任何外部服务的实现都使用完全不同的语言,因此必须是一个单独的限界上下文。我们可以选择与这个 BC 的 Conformist 关系,但这使我们与第三方服务紧密集成。所以我们需要一些东西来与我们语言中的其他限界上下文“交谈”。称它为适配器,网关,随便什么,它充当 ACL。

I need to raise events from my Adapter / Pool wrapping the external service. ACLs are often implemented as Domain Services, but the common advice is not to raise events from a Service. My reasoning is the Domain Service is an interface, and the Implementation (Infrastructure) goes ahead and raises events as needed. These are essentially Integration Events as opposed to typical Domain Events. I don’t own the BC, just the Adapter, so the typical guidance on Domain Events / Aggregates goes out the window? Just raise the event directly?

我觉得有关领域事件的文献有时会有点误导。领域事件的核心概念是:领域中发生的事情。但随着时间的推移,这个概念开始与许多不同但相关的事物混为一谈:读取 CQRS 中的模型预测、最终一致性、事件溯源和跨限界上下文的通信。所以我们必须定义域事件在我们的系统中对我们意味着什么。

域事件是我们域中某些变化的记录,因此逻辑上应该只由聚合引发。然后您选择是否监听和处理这些事件。您还可以决定是在事务内处理还是在事务外处理。我们选择处理内部。

在此之后,我相信我们现在正在跨入消息传递领域。没有什么可以说你不能将域事件作为消息发布,但它已经变得有点不同,或者也许更好地说:现在有更多的目的。一种类型的消息是事件,它不一定是域事件。因此,如果有意义的话,我可以从我的适配器中筹集资金。在这种情况下,它代表我的 BC 之外的事件。尽管处理该事件可能会导致我们 BC 中的域事件。正是这些消息使我们能够实现最终一致性、跨 BC 通信等。您可以将它们称为集成事件、Public 事件、外部事件、AsyncEvents。如果你愿意,可以在发布之前翻译你的领域事件,或者直接发布它们。此时它们是一条消息,无论您是否使用不同的class。

In the instance of the Process Manager requesting a resource from the Pool. Does the Process Manager just call the Adapter directly? Or should this be a Command? Even if the Command is essentially just going to request a resource (ie. no state change to an entity).

视情况而定。如果资源不是系统的业务逻辑和语言的核心部分,或许可以直接作为服务从 PM 调用。如果它在域内启用了一个完整的概念,那么 PM 可能应该发出命令消息。我们可以承认我们的系统正在发生一些状态变化。所以一些聚合(即使只是为了跟踪 PM 中的状态变化)将改变状态并导致领域事件。这最终将作为消息发布。请求将会发生。或者我们可能使用域服务从命令中请求资源。取决于我们想要达到什么。

Any best practises for raising events in this type of scenario? Likewise, if I decided to implement a supporting subdomain with basic Transaction Script. Assume you would just raise the events directly to the Bus as needed from the ACL. There is no Domain Model, and so everything is an Integration Event?

我们承认这些其他事件只是消息。我们会在我们认为合适的时候在我们的 BC 中处理它们。这些不是领域事件。遵循消息传递最佳实践。

Purely for theoretical purposes, as I better try to understand the concepts. A Repository is essentially wrapping a third party persistence service. Is the line of reasoning that the persistence technology is a Bounded Context, and the Repository an ACL / Adapter technically correct?

如果我们学究气,是的。 ORM 等中使用的语言对我的 BC 毫无意义。所以存储库在两者之间进行转换。持久性不是我领域的核心概念,所以我们直接从应用层调用它们。

我们的关键之一是回到 Gregor Hohpe 和 Bobby Woolf 的企业集成模式以及 Vaughn Vernon 的带有参与者模型的反应消息模式。它帮助我们将消息传递概念与领域事件区分开来。