【问题标题】:DDD - aggregate root identity usage across bounded context bounderiesDDD - 跨有界上下文边界聚合根实体使用
【发布时间】:2014-08-22 04:45:22
【问题描述】:

在域模型中对实体身份建模的一种建议方法是创建值对象而不是使用原始类型(例如在 C# 中):

public class CustomerId
{
  public long Id { get; set; }
}

在我看来,这些类应该在整个应用程序中使用,而不仅仅是在域模型中。连同命令和事件,它们可以为有界上下文定义服务契约。现在,在具有多个有界上下文且每个都有单独的服务契约的消息/事件驱动架构中,很容易陷入循环依赖关系。

在有界上下文之间的通信中,您将拥有适配器和翻译器,并且通常大多数属性将被处理为本地值。但是如何处理生活在其他有界上下文中的聚合根的身份呢? 这个问题的一种解决方案是为外部(远程)实体的身份类创建本地上下文兄弟类。但这在某种程度上违反了 DRY 原则。另一种方法可能是将所有有界上下文的合同放在一个程序集中。我在许多 CQRS 示例中都看到了这一点,我认为这是代码异味。作为最后的解决方案,可以在所有合约(事件和命令)中将身份类分解回原始类型,并让每个有界上下文在域模型中组合回他的本地身份类(如果需要)。但这可能会导致复合身份(例如 UserId+TenantId)的身份组合错误。

您如何在项目中处理跨界上下文边界的身份共享?

【问题讨论】:

    标签: c# domain-driven-design cqrs event-driven-design


    【解决方案1】:

    如果您的 Customer 在一种情况下在其他情况下使用不同的名称,例如销售中的 Lead 或运输中的 Receipient,您会怎么做?

    如果他们每个人都有一个 CustomerId,那么它违背了一个上下文的概念和语言不泄漏到其他上下文的目的。

    不要误会我的意思,我完全赞成将聚合 id 封装在一个值对象中。但是每个上下文都应该有自己的实现,其名称与每个上下文的普遍存在的语言一样。

    【讨论】:

    • 点了,这是一个很好的答案。在我看来,当同一个实体存在于两个上下文中(但具有一个主节点,并且可能具有不同的属性)并且以某种方式在下游同步时,这是必须具备的
    • 但是在很多情况下,仅仅为了保存一个外国参考,就用新的基于角色的名称人为地丰富一个领域的无处不在的语言是没有意义的。另一方面,为(隐式)相同概念处理具有不同类型名称的前端或集成层可能会非常尴尬。重要的是要记住,在一个上下文中,类型(封装相同原始值)称为 CustomerId,而在另一个上下文中,它称为 ReceipientId。这种隐含的知识必须以某种方式显式化,可能需要使用互操作翻译器。
    • @Sebastian 正是如此,这正是 Context Map 的目的。 DDD 中描述的一个经常被忽视但仍然有用的工具。
    猜你喜欢
    • 2021-05-29
    • 2019-11-18
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2020-06-14
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多