Ok, attempt two
A few weeks back I decided I was going to use my new found DDD approaches, combined with CQRS and ES, to design the game Risk. And, completely counter to what the practices teach, I went off and started coding a solution with minimal thought or planning. I quickly decided on aggregates and boundaries and off I went, writing my first blog post explaining my proposed solution.
By the way, I mentioned this as well in my first blog post. I'm not really going to go into much detail on the principles of DDD/ES/CQRS but if you want to learn more these are excellent resources:
- Martin Fowler's Blog
- Greg Young's Blog
- Udi Dahan's Blog
- Implementing Domain Driven Design
- Domain Driven Design
So, why did I just dive in like I did?
Well Risk is a pretty well established game, with its own well defined ubiquitous language and the best solution seemed obvious. I just didn't think it required much thought. This was a mistake.
Under the advice of people way more versed in these things than me I decided to take a step back and take a more structured approach at modelling the solution.
Before I go any further it's probably worth you taking a read of the rules of Risk, it won't take long and the next section will make more sense.
Did you read them? I don't believe you, come back when you have.
Ok, now you've read the instructions I will continue.
Instead of closing my eyes and randomly picking some aggregates perhaps it would be better to go right back to the beginning an looked at what I want to achieve:
- A way for people to create a game and invite people to it
- A way for people to play a game
Not much really, I want to keep it simple. The next logical step is to come up with ubiquitous language in which to discuss this problem.
A ubiquitous language is structured around the domain model and used by all team members to connect all the activities of the team with the software. Giving a common ground for both developers, domain experts and users.
So how do we do this? Generally I would suggest this glossary of terms is best derived from a discussion within the team about specifics of the domain. But where to start? Perhaps we should discuss what decisions are available to a user within the domain and let the language fall out of that.
For example in discussing Risk we can say:
A player decides to occupy a territory with an infantry unit
And straight away we can see there are 4 terms here that can start to form the beginning of our ubiquitous language.
Let's try another decision:
A player decides to exchange a Risk card for reinforcements
There's two more terms we can define, this is good. Let's take things a little further and discuss what data will be available in the context of this decision and what data will need to be provided:
The available data is what cards the player is currently holding
The provided data is what cards the player wants to exchange
I think we should probably define what is meant by an exchange as well.
But this is still only part of the story of a decision. We can also look at the information that comes out of this decision.
The knowledge is how many units the player has drafted
There's another one.
And finally we can say when this will be decision is available.
The decision is available when it is the start of the players turn and they have Risk cards available.
So as you can see, when you start looking at the decisions available in domain and the data around them it starts to produce the beginnings of a ubiquitous language. Now you can swap and change these terms afterwards. Maybe call a player a participant but this is a good starting point.
Here is the glossary of these terms:
- Player - A participant in the game
- Occupy - A player is occupying a territory when he places a unit on a territory that has no unit in it
- Territory - The board is broken into territories representing all parts of the world
- Infantry Unit - This is a single token representing a player's army. It is placed on the board to denote which player occupies which territory (and with how big that army)
- Risk Card - These cards are given to players depending on the outcome of their turns and used to draft new infantry
- Reinforcements - Additional units that become available at the start of a players turn
- Exchange/Draft - The process of trading in Risk cards for reinforcements
- Turn - The time in which the designated player is allowed to make choices
There will be other terms that aren't derived from the decisions but these will probably become apparent in your discussions as well.
I've added a complete set of available decisions here and the full glossary is here. Neither of these things are set in stone, There will surely be times where I need to go back and improve the language or add to them. I've tried to follow the pattern of:
- available data
- provided data
Throughout each of the decisions to keep things consistent.
Now that we have a ubiquitous language in which to discuss the domain we can take the next logical step and start looking at our Bounded Contexts and the Entities within them.
If you want to follow along I'm going to host the code on GitHub.