根据依赖关系查找聚合ID

问题描述 投票:0回答:1

我有一个非常混乱的问题,因为我不确定这是否更多是全球设计问题。

我有服务定义了一些聚合和那些聚合发布事件。让我们从服务中选择一个聚合并将其称为A.现在,我定义另一个服务,它有一些应该与A一起工作的聚合,让我们调用第二个聚合B.

当A发布一些事件时,我想向B发送命令(理想情况是通过传奇),但我很难计算B的适当id(A不知道B存在,因此它发布的事件没有任何暗示如何计算id)

我可以想到几种可能的情况:

第一个将基于A的id静态计算B的ID,例如在axon中我可以做类似some-id-${suffix}的事情所以当我从a接收some-id的事件时我可以立即知道它应该被发送到some-id-B

第二个是使用读取方? (我不确定它是如何正确调用的)并查询该东西并尝试根据A id找到B id,但这似乎有点矫枉过正。

有什么我可以阅读,可以引导我通过可能的场景,并给我一个如何处理它们的提示?谢谢!

domain-driven-design axon
1个回答
2
投票

根据我的理解,你有从聚合B到聚合A的关系。这种关系是正常的,它们一直在发生。

注意:由于这个问题很一般而且没有上下文,我可能会遗漏一些东西。如果有一个比描述的更特殊的情况通知我。

This is a great read for aggregate design

注意:在阅读本答案的其余部分之前,请检查Martin Fowler的this video,我强烈建议,因为它详细解释了与事件和命令相关的概念。

注意:因为术语实体也非常重要,从这里开始我将不再使用聚合,所以假设每个实体(玩家,用户,游戏)都是他们自己聚合的根,并且是一致性边界,所以最终的一致性将使用域事件的案例。我现在也会忽略CQRS,以避免谈论读取端和写入端。我们将讨论并实施一个模型

让我们以游戏为例。你有一个玩家应该代表游戏中的用户。玩家实体应以某种方式引用游戏和用户。它可以通过直接引用或ID。在分布式系统的情况下,它将通过ID。对于我们的示例,让我们使用UUID(例如8d670541-aa51-470b-9e72-1d9227669d0c)作为ID,这样我们就可以随机生成它们,而无需定义模式,自动生成顺序号(如SQL数据库中)或特殊算法。假设用户有UserStatistics。因此,当玩家获得分数时(例如通过在射击游戏中杀死其他玩家),如果不存在和更新,则应创建UserStatistics实体。 UserStatistics也应引用User by ID,因此我们从UserStatistics到User具有依赖关系。

UserStatistics将如下所示:

UserStatistics {
  UUID UserID,
  uint KillsCount,
  uint GamesPlayedCount
}

由于播放器在没有用户的情况下不能存在,因此应首先创建用户。因为玩家是游戏的一部分而不是意味着应该首先创建游戏。让我们在泛在语言中定义一些术语。用户通过成为其中的玩家来“加入”游戏。假设游戏将由其他人创建,而不是用户,以避免在用户创建游戏时讨论情况并且同时也应该加入它等等。这应该发生在同一个交易等...游戏将是一个类似于MMO的东西,它由某人创建,普通用户可以加入。

当用户加入游戏时,将使用userID和gameID创建Player实体。创建没有userID和gameID的播放器无效。

让我们讨论命令和事件的问题。命令可以由事件触发。让我们使用观察者模式。一个实体必须观察另一个实体以进行事件。在我们的示例中,这意味着依赖性是从UserStatistics(观察者)到User和Player(主题/消息生成者)。 UserStatistics上的特定命令将作为对从Player和User引发的事件的反应而执行的事实不应以任何方式影响播放器或播放器。通过使用事件故意以被动攻击方式触发特殊命令并不是一个非常好的策略。命令可以由事件触发,但不仅可以触发一个特定的命令。可以触发许多不同的命令,只有依赖的实体,服务或系统应该关心会发生什么。播放器和用户只提供事件。

当用户加入游戏并创建播放器时,它将按ID引用这两个实体,因此它看起来像这样:

Player {
  UUID GameID,
  UUID UserID
}

UserJoinedGameEvent事件也将从User实体引发(它可以从Game中引发但我们将选择User)。它看起来像这样:

UserJoinedGameEvent {
  UUID GameID,
  UUID UserID,
  UUID PlayerID
}

UserStatisticsService可以订阅事件和更新统计信息。

当用户加入游戏时,将开始收集统计数据的过程,我们将更新(或创建,如果它不存在)他的UserStatistics与他玩了多少游戏。在玩家杀人的同时,我们将不得不再次更新统计数据。

将从UserJoinedGameEvent事件触发StartGatheringUserStatisticsCommand。

让我们添加一个看起来像这样的事件PlayerMadeKillEvent:

PlayerMadeKillEvent {
 UUID UserID,
 UUID PlayerID,
 UUID GameID
}

UserStatisticsService将订阅PlayerMadeKillEvents并使用PlayerMadeKillEvent.UserID更新UserStatistics以查找特定用户的统计信息。

当用户退出游戏时,可以引发UserQuitsGameEvent并停止统计信息收集。

在此示例中,我们没有生成特殊ID的特定模式,我们可以引用将首先创建的其他聚合,然后使用其ID。

© www.soinside.com 2019 - 2024. All rights reserved.