【问题标题】:Splitting nested entities keeping invariant within aggregates in DDD拆分嵌套实体在 DDD 中的聚合中保持不变
【发布时间】:2022-01-06 18:19:18
【问题描述】:

我目前正在 crm 应用程序中开发基于消息 imap 的模块,并且我正在尝试使用 DDD 主体连接点。

我从三个主要实体开始,都绑定在 Account Aggregate 下:

  • 帐户 - 电子邮件帐户。有多个文件夹。
  • 文件夹 - 电子邮件帐户中的文件夹(例如收件箱、已发送、草稿)。有多条消息。
  • 消息 - 电子邮件。

在这种情况下,不变量在实际集合上,主要在帐户和文件夹之间:

  • 帐户不能有两个同名文件夹,

  • 帐户不能有多个特殊文件夹(如收件箱或已发送),

  • 邮箱应该有实际的邮件计数。

    Initial aggregate here

这种设计无懈可击。它保持不变,但几乎每个帐户都有大约六个文件夹,其中可以包含数千条消息。加载到内存中的数据量,几乎从未使用过强制拆分 Account Aggregate 的想法。

现在,我有一些选择:

  1. 将其拆分为两个聚合:帐户(以文件夹作为本地实体)和消息

    Two aggregate split here

在这种情况下,我违反了将本地实体(文件夹)引用到另一个聚合(消息)的规则,因为消息绑定到特定文件夹。但是我可以保持帐户和文件夹之间的大部分不变。

  1. 将它们分成三个单独的聚合:帐户、文件夹和消息

    Three aggregate split here

在这种情况下,不会破坏聚合规则,但我会破坏帐户和文件夹之间的不变量。因此,需要使用域服务增加另一层复杂性,并且很可能在一个事务中更新至少两个聚合。 这也迫使文件夹,因为它是聚合之间的实体,而它从来没有成为一个聚合根。

  1. 我可能想念的东西。

此时我会选择第二种解决方案,但在这种情况下拆分这些实体的最佳方法是什么?

【问题讨论】:

    标签: domain-driven-design aggregateroot domain-model


    【解决方案1】:

    我不确定 DDD 是否一定要求聚合中的每个实体都必须作为一个单元加载(尽管许多面向 DDD 的框架很可能会强制执行这样的约束)。只要通过聚合根进行任何访问并且始终如一地维护不变量,就不会真正违反 DDD 准则。

    这可能需要允许延迟加载实体的模型编码;来自 Scala 的 Future 似乎是对“可能尚未出现”方面的合理编码。

    由于无法轻松解决延迟加载问题,我可能会选择第一种方法的变体,但 Message 没有直接引用文件夹。可以以这样一种方式(例如,使用 Bloom 过滤器)实现 Folder,以便快速搜索适当的文件夹。我不确定 Message 需要在文件夹成员身份周围保留哪些不变量(而且您似乎没有表达任何内容)。

    【讨论】:

      猜你喜欢
      • 2022-12-16
      • 2019-06-29
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-11
      相关资源
      最近更新 更多