领域驱动设计如何连接两个上下文?

Domain Driven Design how to connect two contexts?

如何将一个限界上下文与另一个限界上下文连接起来?

例如,我有一个 Cart 上下文和 Product 上下文,当我将产品添加到购物车时首先我想检查产品是否存在,所以我的问题是如何在单体项目中连接上下文?

免责声明
我知道在微服务架构中,您可以请求某些 API 端点来恢复您需要的确切对象并将其映射到值对象。但是在单体中做什么?创建一个桥 class 或创建一个数据库存储库,它将从数据库的某些 table 中检索值对象?

我期待您的想法,谢谢帮助。

至少有 2 种不同的方法来管理它。

上下文之间的数据克隆

在此解决方案中,您为每个上下文使用多个相似的 table,其中数据在每个上下文之间被部分复制。

因此,为了支持您的请求,您必须在用于 购物车[=59= 的上下文中维护 Product 数据的副本]. 要支持这一点,您可以使用:

  1. 使用事件处理程序,每次 产品上下文 发生变化时,您都会更新 购物车上下文
  2. 将信息从一个上下文克隆到另一个上下文的定时作业
  3. 两者的结合
  4. 其他解决方案...

无论如何,无论您选择什么,最重要的是您必须接受最终一致性的概念:您总是使用陈旧数据(可能只有几秒钟的时间,但它已经过时了),因此您必须管理由此可能出现的问题。例如,如果 购物车上下文 中的 产品 包含仓库中不再存在的商品,您会怎么做?

您可以(必须...)在每个上下文的基础结构层中实施此支持代码,因此您让所有其他层都不知道它们管理的数据正在发生什么。最后这个解决方案类似于拥有一堆微服务,只是一切都构建在一个大项目中。

注意:这将是最纯粹的解决方案,每个限界上下文彼此分离,即使它们全部构建在一个项目中。

在多个上下文中重用持久性对象 (db tables)

我在写任何东西之前就先动手了:这个解决方案是可行的,但前提是你真的能很好地控制项目的每个方面。有些人会尖叫这是一种反常,其他人会说在现实世界中你总是要接受妥协。

在这个序言中,我解释了我的意思:而不是在每个使用其数据的上下文中有几个(几乎)克隆 table,用(很多,也许)代码来支持this,原来的table是直接在几个上下文中使用的。因此,每当您在 购物车上下文 中需要 产品 时,您仍然可以通过实施 产品存储库 来自该上下文(购物车上下文),实际上您总是从相同的 table.

获取数据

这有其自身的缺点:可能是上下文需要额外的数据,因此 table 应该扩展(有人会说是污染的),带有额外的字段; table 中的每个更改都可能需要检查使用它的代码,因为 table 是共享的。

但是,应该为管理克隆而编写的许多额外代码都消失了。而且,我的意见,在受控的上下文中,使用整体项目,代码无论如何构建在一起,与第一个解决方案所需的额外工作相比是一个很大的优势。此外,当访问 tables 的代码被深入测试时(没有测试,没有收获),一些问题也更容易管理。


注(个人经验):我用的是第二种方案。我们有一个大单体,有很多 table 数据在多个上下文之间共享。为每个上下文克隆数据的过程是不可行的:只为此花费了太多时间,而没有考虑所有后备情况。共享 tables 要快得多,并且可以开发漂亮的拆分有界上下文。我不使用 JPA (Java ORM),所以我控制加载域实体的 SQL 代码。关于持久性访问的所有内容都经过测试,因此每当有变化时,我都会立即得到报告。