10

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

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

示例:
上下文 A = 用户
上下文 B = 游戏

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

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

4

4 回答 4

17

听起来您的User上下文也需要一个Game实体。但是请注意,这不一定是作为上下文Game根的同一实体。这两个有界上下文可能对 a是什么以及它具有什么属性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.
    }
}
于 2013-09-12T13:55:34.920 回答
4

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

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

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

于 2013-09-12T13:31:07.080 回答
3

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

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

但是如果你选择反腐层,你最好将它们分开(只使用标识符来保持关系),使用适配器翻译器来集成(而不是数据库集成)。

于 2013-09-12T13:12:42.207 回答
0

您必须将 BC 视为逻辑分离,它们指的是人们如何分组以及每个团队之间存在的关系。话虽如此,您也许可以考虑将用户和游戏保持在一个有界的上下文中,将必须在一起的东西放在一起。请参阅大蓝皮书中的这个惊人的视频隐藏课程

于 2021-10-20T04:53:59.893 回答