Java 如何在同一事务中创建ddd聚合并使用其引用更新其他聚合?

Java 如何在同一事务中创建ddd聚合并使用其引用更新其他聚合?,java,domain-driven-design,Java,Domain Driven Design,我想问一下我在游戏实现中使用DDD时遇到的一个问题 我遇到一种情况,根据系统接收到的消息,为玩家创建一个新的聚合。问题在于,该新聚合必须由另一个聚合(表聚合)使用其id引用。该第二个聚合保留一个值对象,其中包含有关表中玩家的信息,如其位置或选择的颜色。玩家聚合存储玩家操作,因为根据玩家数量和他们发布的操作,表聚合可能会变得庞大,如果我将所有内容都保留在表中,那么数据库中的锁争用将代价太高。为了让玩家能够加入到表中,必须首先通过一些验证,如未使用的颜色、已达到的最大玩家数量或玩家未激活的游戏,这就

我想问一下我在游戏实现中使用DDD时遇到的一个问题

我遇到一种情况,根据系统接收到的消息,为玩家创建一个新的聚合。问题在于,该新聚合必须由另一个聚合(表聚合)使用其id引用。该第二个聚合保留一个值对象,其中包含有关表中玩家的信息,如其位置或选择的颜色。玩家聚合存储玩家操作,因为根据玩家数量和他们发布的操作,表聚合可能会变得庞大,如果我将所有内容都保留在表中,那么数据库中的锁争用将代价太高。为了让玩家能够加入到表中,必须首先通过一些验证,如未使用的颜色、已达到的最大玩家数量或玩家未激活的游戏,这就是为什么此值对象存储在表中,并包含来自玩家的信息

因此,基于此,我只在玩家发出要存储在表外的第一个操作时创建玩家聚合。问题在于,该表可能包含引用尚未创建的聚合的值对象,这使得代码在强制检查空引用时看起来很难看。另一个选项,即首先创建播放器聚合,也会破坏设计,因为创建播放器的验证首先发生在表上。由于系统的并发性,首先在表上进行验证,然后创建玩家聚合,然后在接收到来自创建的事件时更新表,这可能会导致许多竞争条件。我唯一能想到的就是更新同一事务中的两个聚合,但这违反了DDD规则

有什么好的解决办法吗?我想最终这将与设计有关,但我想不出任何不引入性能问题的方法


谢谢

通常,您的部分问题可以通过从领域和通用语言的角度来解决

  • Udi Dahan有一个关于聚合根如何不是凭空出现的,而是作为一个域操作的结果,该域操作必须是一个一流的无处不在的语言公民。在您的情况下,播放器可以不是由应用程序服务创建的,而是由
    AR最接近域源的

    请注意,我不一定主张像Udi的示例中那样保留对其他根的完整引用,但您可以将其替换为
    Table.ReceivePlayer(…)
    返回新创建的播放器,然后应用程序服务可以将其添加到
    PlayerRepository
    。由于在该场景中,
    Player
    不扮演聚合根的角色(即修改和不变强制的单个入口点),而是扮演简单实体的角色,因此您可以合法地将所有这些打包到单个事务中

  • 驱动聚合建模的力量基本上是真正的不变量、并发性和性能。为了证明您是如何建模的,您声明,如果我将所有内容都保留在表中,那么表聚合可能会变得庞大,并且数据库中的锁争用代价太高

    我认为,进一步探索这一争论的真正含义,并将领域术语置于其背后,丰富您无处不在的语言,将是值得的。表是否大量并发?为什么呢游戏是否有玩家修改的可变共享状态?玩家是否需要根据其他玩家的动作做出决定,如果同时采取行动,会引入某种偏见?所有这些在领域术语中是如何翻译的?额外的
    Player
    聚合为您带来了什么

    就性能而言,一个庞大的
    集合是什么样子的,它会对系统产生怎样的影响

  • “不跨多个聚合的事务”规则只是将聚合作为一致性边界的必然结果,它不是一成不变的。在一个事务中创建小型的、独立一致的聚合并对其中的多个聚合进行大量修改是没有意义的,因为这样会产生不必要的争用,并随之产生潜在的并发问题。但是在一个场景中,除了唯一的
    AR之外,不存在任何并发问题,而且创建过程中肯定存在这种情况,因为没有其他人知道添加了播放器,这就好像您只修改了一个聚合,而规则实际上不再适用一样

    如果您在99%的修改案例中遵守规则,但在1%的创建案例中不遵守规则,那么您仍然在执行规则


类似于
player=table.newPlayer(…);玩家保存。保存(玩家);tableRepository.save(表)
where
Table
只向内部集合添加一个VO。在这里,您不会在同一事务中修改两个聚合,因为播放器只是创建的,而不是修改的。因此,播放器实例上不存在争用。您真的可以这样做吗?我认为不在同一事务中修改两个聚合的整个过程也包括创建。在我的情况下,即使这样也不行,因为球员离开桌子后也不会被从球员的位置上移除。我必须检查,因为我不知道我是否会打破其他东西。另一个要求是为玩家存储快捷方式,但这可能是在另一个有限制的上下文中,因此在玩家离开后删除他仍然是安全的。但是我想首先知道在ddd中同时更新和创建是否有效。是的,我相信它是有效的,因为并发冲突的风险不会增加。例如,您是仅修改
集合还是修改
ag