在领域驱动设计中 - 单个公共实体模型,还是每个有界上下文的模型?

问题描述

在领域驱动设计中,我们尝试分离功能区域(有界上下文)之间的关注点,并最小化上下文之间的依赖关系。同一个实体在不同的上下文中可以有不同的内部表示。但是在上下文(例如公开的 API 和/或事件)之间的通信中,我们是为每个数据消费者定制实体的表示,还是使用通用表示?

例如,采用众所周知的销售和支持上下文之间的分离(由 Martin Fowler 绘制)。这两个上下文都需要了解客户和产品。但是在支持上下文中,客户有一个工单列表;而在销售上下文中,客户被分配到一个区域。很可能,内部表示在这两种情况下会完全不同。但是对于公开​​的 API 和事件,我们是否有一个包含这两个功能的单一客户模型,或者每个上下文有多个模型。

解决方法

拥有单独的有界上下文的要点是可以自由地以适合该特定上下文的方式表达实体,而不必担心系统的其余部分。这就是您在有界上下文中主要管理功能清晰度和数据神圣性的方式。因此,让客户在不同的上下文中以不同的方式表示绝对是有意义的。

您可以将单独的有界上下文视为不同的微服务。它们单独部署和扩展,不共享数据。他们的 API 是独立的,迎合他们自己上下文的功能。他们拥有模型,并负责在其边界内维护数据的完整性,而无需担心应用程序的其余部分。

请注意,当相关概念有不同的模型时,您通常必须在上下文中保持相同的身份。您可以通过从初始化实体的第一个上下文发布域事件来实现这一点,以便其他上下文适当地填充自己。

在 Fowler 的示例中,销售上下文可能是初始化客户的第一个上下文。因此,销售上下文将生成身份。然后,支持上下文通过侦听 CustomerCreated 域事件(例如,预计来自客户的未来支持电话)向自身添加记录。

当您需要整理来自不同有界上下文的数据时,您通常会编写一个单独的查询或报告服务,该服务在域逻辑之外使用简单的查询进行操作。获取数据并将其组织起来以进行展示的视图/查询通常位于域逻辑之外。