many-to-many - 具有多对多关系的 DDD 聚合设计示例
问题描述
我想通过一个建模练习来尝试更好地理解 DDD,特别是在存在多对多关系的情况下
让我们以 Xbox 用户及其成就为例。
如果您不熟悉,这是背景:Xbox 上的每个游戏都有成就。用户将拥有他们拥有/玩过的游戏列表,他们可以解锁这些游戏的成就。
这里是多对多的关系,一个用户可以有很多游戏,一个游戏可以有很多用户。
不用多说,这里肯定有两个聚合根。用户和游戏。游戏聚合根有一个成就列表。
我的困惑来自于跟踪特定游戏的用户进度。例如他们有哪些游戏,以及他们在每场游戏中取得的成就。
您现在将如何建模这是 DDD?
用户游戏和用户成就将包含有关每个进度的信息。
这是我目前认为的解决方案,但是对吗?
一个游戏的进度和它的个人成就似乎也有联系,我会说这是它自己的总根。这是因为就像游戏及其成就一样,它可能具有交易边界。当您在游戏成就上取得进展时,这可能会影响游戏的进度(例如,解锁成就会增加游戏玩家获得的总得分。)
我一直听说你要解决多对多关系,这通常没问题,但在这里,关系有自己的数据,我认为这种关系也不属于。
您可能会争辩说您会将它放在用户聚合上,但我担心它会增加该用户聚合的权重,并且没有理由让它存在。我不认为有任何事务边界,我不喜欢当你想加载它时必须加载所有用户的游戏。即使这是延迟加载,我担心它可能会导致并发问题?
这就是为什么我认为这里的多对多关系是有效的,以及为什么新的聚合根可能是合适的。
也是名称用户游戏进度甚至正确。知道域,你有什么建议?
谢谢,任何帮助都会得到广泛的应用。
解决方案
您在这里寻找的是领域事件。从微软文档:
使用域事件显式地实现域内更改的副作用。换句话说,使用 DDD 术语,使用领域事件显式地实现跨多个聚合的副作用。或者,为了获得更好的可伸缩性并减少对数据库锁的影响,请在同一域内的聚合之间使用最终一致性。
“游戏的进展”对我来说似乎不是一个总根。要更新“游戏进度”,您可以从聚合中引发域事件,例如“User_Moved”,并从User
聚合中引发类似事件Game
。然后,您可以订阅这些事件以更新游戏进度。此外,由于域事件是在内存中的,因此您可以在单个事务中实现这一点。
推荐阅读
- python - Pymongo MongoDB - 如何从具有 3 个要索引的数组中的数组中删除对象
- r - 在 R 中突出显示值(corrplot)
- mysql - 创建一个查询来计算客户编号 100019 的所有购买。此查询的输出应该是订单号、零件编号等
- python - 如何使用 dbfaker 生成非重复数据
- php - 添加具有订单详细信息功能的自定义按钮 - Magento 2
- php - 根据 Laravel 8 中的 URL 参数更改要连接的 MySQL 数据库
- python - 如何通过键值搜索字典并将字段附加到 JSON?
- gensim - `FastText.wv.save_word2vec_format()` 创建一些条目,在一行上有两个单词
- toggle - 似乎 else 语句未在切换功能中执行
- snowflake-cloud-data-platform - 如何将增量更新数据转换为雪花中的结构化表