0

I am designing a game in a corporate business. Its a turn based game .

Invariants:

a) A Game has two Players at least , a Start Date and other properties.

b) Each Player plays a turn inside a Game.

c) A member when joins a Game becomes a Player.

d) A member could be a Player in 0-n Games.

My main problem is how to aggregate the concepts.

enter image description here

At first i think that member is its own aggregate.Since others only maintain a references to it.

Later it's possible that Game is the root of another aggregate , including player and turn. Whit that I could ensure:

  • invariant a) when i create it.
  • invariant b) the aggregate haves all it needs inside the aggregate to meet the invariants.
  • invariant c) => not responsibility of this aggregate

I would like to hear your approaches since I am really stuck.

X.Otano
  • 2,079
  • 1
  • 22
  • 40
  • You got them right. Member Aggregate and Game Aggregate. Game has 2 players, turns and nextPlayer as Value objects. – Constantin Galbenu Sep 08 '18 at 16:31
  • How Next player and turn will be a value object? It’s game like trivial pursuit. I don’t maintain any historical moves of the players.just who is next turn. Does it changes your proposal? – X.Otano Sep 08 '18 at 21:13
  • nextPlayer is an ID or an index (0 or 1) so clearly a VO. – Constantin Galbenu Sep 09 '18 at 00:41
  • And then what is `turn` for? – Constantin Galbenu Sep 09 '18 at 00:42
  • @ConstantinGalbenu hi, next turn it’s and iD of the next player who have to play. It s like the winner player of a game. You say are VO but, they refer to an entity. Could you explain better why they become VO? – X.Otano Sep 09 '18 at 16:15
  • I don’t get how an entity ID would become a value object . Is that possible? – X.Otano Sep 09 '18 at 16:18
  • an entity's ID is a VO, always immutable. Maybe it has no behavior, but VO is what describe it the best. What could it otherwise be? – Constantin Galbenu Sep 09 '18 at 16:25
  • A simple reference to Player entity. Player TurnOf{get;private ser;} – X.Otano Sep 09 '18 at 16:26
  • it can be but then player is a Value object that once set would not change. Once a game starts, the players would not change, at least not in this Bounded context. – Constantin Galbenu Sep 09 '18 at 16:57
  • I don’t get that. Turn is changing during a game play. And the turn is a reference to a player who is an entity since it some that exists in the domain ( i need to identify them uniquely) . Why will you convert turn to be a VO?The reason is that is a reference to entity ID is inmutable is kind of weird. Following that , evertything could be a VO – X.Otano Sep 09 '18 at 17:02
  • not turn, but Player. In this BC it is a VO – Constantin Galbenu Sep 09 '18 at 17:03
  • Could you explain better?thanks – X.Otano Sep 09 '18 at 17:06

2 Answers2

1

In a turn based game like naughts-and-crosses, checkers, chess, backgammon, I would normally expect the "game" aggregate to include the moves and the current position of the tokens/board/tableau.

The justification being that figuring out if the game history is internally consistent requires being able to see all of the history "together", so that you can detect contradictions.

A way to see this is to notice that two different memberships don't normally have any dependencies on each other, so it makes sense for them to be different instances of an aggregate. If a game is to be shared by two members, then it can't really belong to either member alone, so it must be some third aggregate that is tracked separately.

VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
  • This game is turn based, but the state of a game is known by which slices are owed by each player. When a player owns the 6 slices it’s the winner. Does this invariant changes your proposal? – X.Otano Sep 09 '18 at 16:17
1

You got it right, with 2 Aggregates but now you need to understand why.

The Member Aggregate owns the data and the behavior for the members. What a member means, how to ca become a member, when can it change its name, when can it be unlocked and so on.

The Game Aggregate owns the rules of the game and two players. It has all the data it needs to protect its invariants and to display it in the UI. The invariants it protects are:

  1. at least two different players must exist before the game starts and one member can play only one time in the same game
  2. each player makes a move, one after another
  3. when a player is out-of-game it cannot move anymore
  4. and so on

In order to protect the second invariant, the Game has a turn state that is a pointer to the next Player. But here comes the interesting question: what is a Player, how can it be represented in the code?

A player is a pointer to one of the Members. It has all the attributes that are needed by the Game aggregate or the UI. The Game Aggregate needs its ID in order to protect the first invariant (to detect duplicate IDs), in order to load all the games that a Member plays and in order to display in the UI the name of the Player so that the other players will know with who they are playing.

The Player seems to be an Entity, because it has an ID and another property, it's name, but it isn't because it doesn't own the name nor the behavior for it: when and how a member can change it's name is controlled by the Member Aggregate, the Player's name is updated without the Player to have a word on this, maybe in the background.

From the Game's point of view, a Player is just a plain object, immutable, with an ID and a name as a string. This is a perfect candidate for a Value object.

So, although a Member is an Aggregate root (which is a type of entity), a Player, having the same ID and name as a Member is not an Entity but a Value object.

Constantin Galbenu
  • 16,951
  • 3
  • 38
  • 54
  • Very great explanation. So , do you suggest to raise a domain event when member info is updated? So there will be a handler that will update all the players who’s ID matches the event. Then a new VO Player will be created with the new data. Am I right? – X.Otano Sep 10 '18 at 08:16
  • @Badulake yes, using events is the best possible way – Constantin Galbenu Sep 10 '18 at 08:34