Dns 领域驱动设计-如何聚合基于回合的游戏
我正在一家公司设计一款游戏。这是一个回合制游戏 不变量: a) 一场游戏至少有两名玩家,一个开始日期,另一个开始日期 财产 b) 每个玩家在游戏中玩一个回合 c) 成员 当你加入一个游戏时,你就成为了一名玩家 d) 一个成员可以是游戏玩家 0-n游戏 我的主要问题是如何聚合这些概念 起初,我认为该成员是它自己的聚合,因为其他成员只维护对它的引用 稍后,游戏可能是另一个聚合的根,包括玩家和回合。我可以确保:Dns 领域驱动设计-如何聚合基于回合的游戏,dns,domain-driven-design,ddd-repositories,aggregateroot,Dns,Domain Driven Design,Ddd Repositories,Aggregateroot,我正在一家公司设计一款游戏。这是一个回合制游戏 不变量: a) 一场游戏至少有两名玩家,一个开始日期,另一个开始日期 财产 b) 每个玩家在游戏中玩一个回合 c) 成员 当你加入一个游戏时,你就成为了一名玩家 d) 一个成员可以是游戏玩家 0-n游戏 我的主要问题是如何聚合这些概念 起初,我认为该成员是它自己的聚合,因为其他成员只维护对它的引用 稍后,游戏可能是另一个聚合的根,包括玩家和回合。我可以确保: 不变a)当我创建它时 不变量b)聚合在聚合中拥有满足不变量所需的所有内容 不变c)=>
- 不变a)当我创建它时
- 不变量b)聚合在聚合中拥有满足不变量所需的所有内容
- 不变c)=>不属于此聚合的责任
我很想听听你的方法,因为我真的被卡住了。在一个基于回合的游戏中,如零和十字架、跳棋、国际象棋、双陆棋,我通常希望“游戏”集合包括移动和令牌/棋盘/画面的当前位置 理由是要弄清楚游戏历史是否在内部一致,就需要能够“一起”查看所有历史,这样才能发现矛盾
了解这一点的一种方法是注意到两个不同的成员身份通常彼此之间没有任何依赖关系,因此它们是聚合的不同实例是有意义的。如果一个游戏由两个成员共享,那么它不可能真正属于任何一个成员,因此它必须是单独跟踪的第三个聚合。在基于回合的游戏中,如零和交叉、跳棋、国际象棋、双陆棋,我通常期望“游戏”聚合以包括移动和令牌/板/表的当前位置 理由是要弄清楚游戏历史是否在内部一致,就需要能够“一起”查看所有历史,这样才能发现矛盾
了解这一点的一种方法是注意到两个不同的成员身份通常彼此之间没有任何依赖关系,因此它们是聚合的不同实例是有意义的。如果一个游戏由两个成员共享,那么它不可能单独属于任何一个成员,因此它必须是单独跟踪的第三个聚合。你做对了,有两个聚合,但现在你需要理解为什么 成员聚合拥有成员的数据和行为。会员的意思是什么,如何成为会员,何时可以更改其名称,何时可以解锁等等 游戏集合拥有游戏规则和两名玩家。它拥有保护其不变量并在UI中显示所需的所有数据。它保护的不变量是:
回合
状态,它是指向下一个玩家的指针。但这里有一个有趣的问题:什么是播放器,如何在代码中表示它
玩家是指向其中一个成员的指针。它具有游戏聚合或UI所需的所有属性。为了保护第一个不变量(检测重复ID),为了加载成员玩的所有游戏,为了在UI中显示玩家的名字,以便其他玩家知道他们在玩谁,游戏聚合需要它的ID
玩家似乎是一个实体,因为它有一个ID和另一个属性,它的名称,但这不是因为它不拥有名称或它的行为:成员更改名称的时间和方式由成员聚合控制,玩家的名称被更新,而玩家对此没有发言权,可能是在后台
从游戏的角度来看,玩家只是一个普通的对象,不可变,ID和名称都是字符串。这是值对象的完美候选对象
因此,尽管成员是聚合根(这是一种实体类型),但与成员具有相同ID和名称的玩家不是实体,而是一个值对象。你说得对,有两个聚合,但现在你需要理解为什么
成员聚合拥有成员的数据和行为。会员的意思是什么,如何成为会员,何时可以更改其名称,何时可以解锁等等
游戏集合拥有游戏规则和两名玩家。它拥有保护其不变量并在UI中显示所需的所有数据。它保护的不变量是:
游戏开始前必须至少有两名不同的玩家,且一名玩家只能在同一游戏中玩一次
每个玩家一个接一个地移动
当一个玩家退出游戏时,它就不能再移动了
等等
为了保护第二个不变量,游戏有一个回合
状态,它是指向下一个玩家的指针。但这里有一个有趣的问题:什么是播放器,如何在代码中表示它
玩家是指向其中一个成员的指针。它具有游戏聚合或UI所需的所有属性。为了保护第一个不变量(检测重复ID),为了加载成员玩的所有游戏,为了在UI中显示玩家的名字,以便其他玩家知道他们在玩谁,游戏聚合需要它的ID
玩家似乎是一个实体,因为它有一个ID和另一个属性,即名称,但这不是因为它不拥有名称或行为:何时和如何