DDD:阻止外部服务呼叫和事件

时间:2020-06-23 10:15:06

标签: service domain-driven-design messaging bounded-contexts domain-events

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

可以使用许多第三方服务,因此我们有一个提供公共接口的适配器。一次只能提供X个服务实例(创建和销毁它们的开销很大),因此它们是从Pool中检索的。

外部服务是长时间运行过程的一部分。该过程将由过程经理来实施。计划了一个实体,然后它向对象池请求资源,当资源空闲时,它执行一个动作,然后记录结果,并将资源返回给池。此过程的两个部分(请求可用资源和执行操作)可能会花费一些时间,并且会阻塞调用。因此理想情况下,这些操作应该异步进行吗?

这意味着当资源空闲时,并且在计算操作结果时,外部服务需要引发事件。我看到的每个示例都提供了从聚集引发事件的指导。当外部系统(在这种情况下是通用子域?)需要报告事件时,它很少。所以我的问题是:

  • 我的理解是,任何外部服务基本上都是一个单独的有界上下文。在这种情况下,通过将服务隐藏在公共接口后面,适配器和池基本上可以充当ACL。这个假设正确吗?

  • 我需要从包装外部服务的适配器/池中引发事件。 ACL通常作为域服务实现,但是常见的建议是不要从服务引发事件。我的推理是域服务是一个接口,实现(基础结构)将继续进行并根据需要引发事件。这些本质上是集成事件,而不是典型的域事件。我不拥有BC,而仅拥有适配器,所以关于“域事件/聚合”的典型指南不在窗外吗?只是直接提出事件?

  • 在流程管理器的实例中,从池中请求资源。流程管理器是否只是直接调用适配器?还是这应该是一个命令?即使Command本质上只是请求资源(即,实体的状态没有变化)。

  • 在这种情况下是否有引发事件的最佳实践?同样,如果我决定使用基本的Transaction Script实现支持的子域。假设您只是根据需要从ACL直接向总线提出事件。没有域模型,那么一切都是集成事件吗?

  • 纯粹出于理论目的,因为我最好尝试理解这些概念。存储库实质上是包装第三方持久性服务。持久性技术是有界上下文,而存储库是ACL /适配器在技术上是正确的吗?

我一直在努力寻找有关上述内容的具体指导,因此请多多指教。

1 个答案:

答案 0 :(得分:0)

经过一些进一步的研究,我将可以回答我自己的问题。

我的理解是,任何外部服务基本上都是独立的 有限的上下文。在这种情况下,适配器和池基本上是 通过将服务隐藏在通用设备后充当ACL 接口。这个假设正确吗?

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

我需要从我的适配器/池中引发事件,将外部包装 服务。 ACL通常作为域服务实现,但常见 建议不要从服务中引发事件。我的理由是 域服务是一个接口,而实现 (基础结构)继续进行并根据需要引发事件。这些是 本质上是集成事件,而不是典型的域事件。一世 不拥有BC,而仅拥有适配器,因此有关Domain的典型指南 事件/汇总消失了吗?只是提出事件 直接吗?

我认为有关领域事件的文献有时可能会引起误解。域事件的核心概念是:域中发生的事情。但是随着时间的流逝,这个概念已经开始与许多不同但相关的东西混为一谈:读取CQRS中的模型预测,最终一致性,事件源以及跨有限上下文的通信。因此,我们必须在系统中定义域事件对我们意味着什么。

域事件是我们域中某些事物发生变化的记录,因此从逻辑上讲,它仅应由聚集引发。然后,您选择是否监听和处理这些事件。您还决定是在事务内还是外部进行处理。我们选择在内部处理。

此后,我相信我们现在正在跨入Messaging。没什么好说的,您不能将域事件作为消息发布,但是它变得有些不同,或者也许更好地表述:现在已经增加了用途。消息的一种是事件,它不一定是域事件。因此,如果可以的话,我可以从适配器上提出。在这种情况下,它表示我的BC以外的事件。尽管处理该事件可能会导致我们卑诗省发生域事件。这些消息使我们能够实现最终的一致性,在BC之间进行通信等。您可以将它们称为集成事件,公共事件,外部事件,AsyncEvent。如果需要,在发布之前翻译您的域事件,或者直接发布它们。此时,无论您是否使用其他类,它们都是一条消息。

在流程管理器的实例中,向 游泳池流程管理器是否只是直接调用适配器?要么 这应该是命令吗?即使命令本质上只是 将要请求资源(即,实体的状态没有改变)。

这取决于。如果资源不是系统的业务逻辑和语言的核心部分,则可以直接将其作为服务从PM中调用。如果它在域中启用了集成概念,则PM可能应该发出一条Command消息。我们可以确认系统中正在发生某些状态更改。因此,某些汇总(即使仅用于跟踪PM中的状态更改)也会更改状态并导致域事件。这最终将作为消息发布。并且请求将发生。或者,也许我们使用域服务从命令中请求资源。取决于我们要实现的目标。

在这种情况下是否有引发事件的最佳实践? 同样地,如果我决定使用基本的 交易脚本。假设您只是将事件直接引发 根据需要从ACL中选择总线。没有域模型,因此 一切都是整合事件吗?

我们只是承认这些其他事件只是消息。我们认为合适时,在我们的卑诗省处理它们。这些不是域事件。遵循消息传递的最佳做法。

纯粹出于理论目的,我最好尝试理解 概念。仓库实际上是包装第三方 持久性服务。是坚持的道理 技术是有界的上下文,而存储库是ACL /适配器 技术上正确吗?

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

对我们来说,关键之一是追溯到Gregor Hohpe和Bobby Woolf的企业集成模式,以及Vaughn Vernon的使用Actor模型的反应消息模式。它帮助我们区分了消息传递概念和域事件。