【问题标题】:DDD - How to design associations between different bounded contextsDDD - 如何设计不同有界上下文之间的关联
【发布时间】:2013-09-16 15:31:53
【问题描述】:

我已经设置了一个使用 ORM 填充的域项目。域包含不同的聚合,每个聚合都有自己的根对象。 我的问题是应该如何处理跨越聚合边界的属性?

  • 这些属性是否应该简单地忽略边界,以便有界上下文 A 中的域对象引用上下文 B 中的对象?
  • 或者,是否应该没有从上下文 A 到 B 的直接链接,并且上下文 A 中的对象是否具有可用于通过 B 聚合根从 B 获取域对象的“int ContextBId”属性?
  • 或者……

一个例子:
上下文 A = 用户
上下文 B = 游戏

Users 上下文中有一个对象UserOwnedGames。此对象有一个属性User,它是对同一Users 上下文中的对象的引用。该对象还具有Game 的属性,该属性显然不在用户中,而是在Games 上下文中。

这种关系会(或应该?)如何?数据库中很清楚(即2个外键),但代码应该是什么样子?

【问题讨论】:

    标签: domain-driven-design aggregateroot bounded-contexts


    【解决方案1】:

    您必须将 BC 视为逻辑分离,它们指的是人们如何分组以及每个团队之间存在的关系。话虽如此,您可以考虑将用户和游戏保持在一个单一的有界上下文中,将必须在一起的东西放在一起。 请参考这个精彩的视频Hiden lessons from the big blue book

    【讨论】:

      【解决方案2】:

      听起来您的User 上下文也需要Game 实体。但是请注意,这不一定是相同的 Game 实体,它是 Game 上下文的根。这两个有界上下文可能对 Game 是什么以及它具有什么属性有不同的想法。只有身份将两个 Game 对象联系在一起。

      User Context
      {
          Aggregate Root User
          {
              Identity;
              Name;
              OwnedGames : List of Game value entities
          }
      
          Value Entity Game
          {
              Identity;
              Name;
          }
      }
      
      Game Context
      {
          Aggregate Root Game
          {
              Identity;
              Name;
              Owner : User value entity
              HighScore : int
              TimesPlayed : int
              ... A whole bunch of other properties which are not relevant in the User context
          }
      
          Value Entity User
          {
              Identity;
              Name;
              // No OwnedGames property, in this context we don't care about what other games the user owns.
          }
      }
      

      【讨论】:

      • 非常有趣的概念。我从没想过同一事物有多个版本。
      • 在 DDD 中,没有关于什么是“是”的全局、明确的概念,“事物”在某些情况下只是一个“事物”。
      • 那么如何处理跨上下文同步对同一属性的引用?假设我在 User Context 中更新了 User 的 Name 属性,如何让它在 Game Context 中更新 User 的 Name 属性?您是否在请求时使用 getter 来访问其他上下文?或者你有什么方法可以使两者同步?
      • 嗨@Balrog30,这将是域事件的来源。见slideshare
      【解决方案3】:

      您应避免跨 BC 引用数据库 - 您不应尝试确保来自不同 BC(事务)的聚合之间的引用完整性。理想情况下,事务应该只存在于单个聚合中,甚至不存在于 BC 中。

      最好对 ID 使用简单的值对象 - UserId 和 GameId - 并在需要时将它们分配给实体。这样,那些“远程”实体完全分离,因此您不必担心它们的连接。可以使用消息传递平台实现同步。

      如果您有空闲时间阅读这些有价值的文章(作者 Vaughn Vernon):

      【讨论】:

      • 嗨,但是如果我想在数据库级别强制执行数据完整性
      【解决方案4】:

      这取决于您使用的有界上下文策略。

      如果您选择共享内核,我认为它们之间有直接关系是可以的(直接引用或标识符引用,我相信其他人会在其他答案中解释优缺点)。您还提到了这些由数​​据库表集成的对象。

      但是如果你选择anti-corruption-layer,你最好将它们分开(只使用标识符来保持关系),使用adapter-translator来集成(而不是数据库集成)。

      【讨论】:

        猜你喜欢
        • 2016-03-08
        • 2021-05-28
        • 1970-01-01
        • 1970-01-01
        • 2013-11-27
        • 2021-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多