Incremental Event Sourcing
An extreme example of how to approach an application with Agility and Slicing
How does Agility look when paired with Event Sourcing? How does it look when increments get manifested in code? Let me try to explain what I meant when I wrote “True Agility requires Event Sourcing.
And to not further upset sensitive developers hearts and minds very attached to their Agility and Object-Orientation and data persistence approaches, I want to do that in a playful way. How about a dialog with a customer?
Yes, let’s assume there is customer Pete eager to get an application for himself and his loved ones. He’s approaching developer Darline, a fan of Agility and Event Sourcing. How would an incremental-iterative collaboration between the two look like?
In order to fit it into a single article, of course the domain of the application needs to be easy to understand and small. Still I believe that even from such small examples one can learn a lot.
Furthermore, I want to take agility to the extreme by deliberately keeping each increment very small and trying to withhold as much information as possible. This is, of course, the opposite of what is usually attempted. But ultimately, it reflects reality: even if you try to coax as much information as possible out of the customer at every moment, there is always more information that remains unknown. You inevitably realize this over time. Who hasn’t exclaimed, “What? Couldn’t you have told me that earlier?”
Ok, the stage is set. Let’s listen to Pete and Darline…
Increment 1 — It’s a game
Darline: Pete, thanks for asking me to develop this software for you. You sure want to see results quickly. So let’s jump right in. What do you want to do with that software?
Pete: That sounds great, Darline! I like your hands-on approach. Yes, let’s get going: What I want to do is play a game with another person, maybe with my daughter. We like to sit down in front of my computer for a round or two of a fun game. We enter our names and off we go. Then what I’d like…
Darline: What an exciting idea, Pete! But, please, stop here. Don’t tell me more. I’d like to run with this and show you how the game could look. I’ll come back to you with something to try out and then refine. It’s easier for both of us to develop and implement your ideas. Ok?
Pete: Ok. If you say so. I thought, I was supposed to tell you all of my idea up-front.
Darline: Yes, that’s how software is usually is done. But trust me, we can do better than that. Too much information from you can be overwhelming for me and lead me to decisions I might later regret. Also you will come to understand your own thinking much better if I put working software at your fingertips — even if that’s not perfect yet.
So, please, sit tight for a minute…
[Darline thinks and codes for a little while…]
Darline: What do you think about this? You start the application and it asks for both player names…
…and then it starts a new game:
Please don’t pay attention to the strange number. It’s a technical detail the program only now displays. It will go away soon. I just did not know much about the user interface, so I figured I print the player names and some info for myself.
What do you say?
Pete: This is looking like a start, indeed. I am impressed how quickly you came back to me with a running program. And if this help me getting more of what I want more quickly, I am happy to play along.
I’m ok with starting the game like this in a terminal window. And, sure, being asked like this for our names is fine. But of course there is more…
Darline: Sure! This only was the beginning. I am eager to learn more about the game idea you’re having. But remember: Better to progress in little steps. What’s a small addition you can think of for the application?
Increment 2 — Players move in turn
Pete: Hm… this is kind of hard for me. There are so many ideas in my head. But I will try to break them apart into small chunks.
Darline: Thank you, Pete! That would be great. I know, it’s kind of unusual not to lay out your whole vision for the game. But trust me, in the end it will be faster and closer to what you really want, if we just do baby steps.
Pete: Ok, baby steps. Here is the next one. I don’t know, if it’s the best one.
Darline: That’s fine. Better than a perfect next step is a good tiny step.
Pete: Tiny, ok: The players take turns in making their moves. Player 1 starts, then player 2 and so on. This end when…
Darline: Great! Let’s stop here. Don’t tell me more. I want to focus on “players take turns”. That’s a tiny step forward. Give me a minute to show you how that could look…
[Darline thinks and codes for a little while…]
Darline: Check this out, Pete! You start the game as before and then players can move in turn:
Since I don’t know what the game is about, the players are just asked to hit ENTER for their move. That will of course be replaced by a real move — once we get to that.
Pete: It’s not yet the game I have in mind, but I see the step forward. Yes, it’s how it should be working. Players are addressed with their name so they know whose turn it is. That’s ok for not.
Darline: Cool! So, let’s move on to the next feature. Remember: give me just a little bit of information.
Increment 3 — The game has an end
Pete: I’ll try. This is becoming a fun game in itself. A kind of a challenge: Can I think still smaller and smaller. Thanks for the challenge!
Here you go: The players make their moves until the game is finished.
How is that for a baby step?
Darline: I see you’re a quick learner, Pete! Yes, that’s a thin slice of the whole requirements you have in your head already. I can work with that. Just let me ask: Why or when does a game finish?
Pete: A game is finished when either of the players wins it or it’s a tie. But I won’t tell you the conditions for that. No, no, baby steps, as you wanted it.
Darline: That’s perfectly fine. Thanks for following me in my strategy. Ok, there are two ways a game can end: a player actually wins it or no player wins because no more moves in that direction can be made for some reason. I can work with that. No more details needed.
But I am going to make an assumption for now: the game will end after a couple of moves automatically for a reason randomly picked. Just for demonstration purposes.
[Darline thinks and codes for a little while…]
Darline: Here’s your game with winners and losers, Pete:
As you can see, the games run for a while and then it’s randomly decided how they and if there is a winner, who it is. Until then players take turns with their moves.
Pete: Excellent! That’s as close to reality as you could get without knowing what the game is about. I trust this is not just for show, but there is really meat to your code and you’ve prepared it for what’s to come.
Darline: Of course! At the surface this looks trivial and arbitrary. But I can assure you, I made meaningful changes under the hood. It’s just the decision criteria which where randomness plays a role. Other than that this judgement is placed thoughtfully in the code and leaves a real result.
What’s next?
Increment 4 - Players placing tokens
Pete: Let me think how I can throw you only a morsel from my wealth of ideas for the game, and still get to see some progress. How about this:
Players move by placing a token on a game board. Each player has her own token, a symbol, and chooses a field on the game board to place it. Fields are identified with an index larger or equal to 0.
Does that sound small enough?
Darline: Definitely. It’s small and somewhat cryptic. I am wondering what game this will turn out to be. But I can work with that.
[Darline thinks and codes for a little while…]
Darline: Here you go! The player now somewhat are playing a game already.
With each turn the player is asked to enter the index of the field on the board where her token should go. I am not checking the index. Yet. But a number is expected.
As you can see then the current state of the board is displayer. Right now it’s just a list of field indexes with the name of the player who put a token there. You sure will tell me sooner or later how a game actually looks, I presume. Then I will adapt the display. For now the list is just to check the moves are registered correctly.
Pete: This looks great, even though it’s not really close to what I have in mind. I understand how you make temporary assumptions to fill in the gaps I am leaving in my requests. Because you told me so.
The user interface is nothing to show off. In time, I trust, this will change, though. Once I choose to become specific about it in another baby step.
Darline: That’s correct. Please be patient. All your requirements will be met. Sooner or later. In the order you choose.
How do you want to proceed? You see I left in the code the automatic random decision about the end of the game.
Increment 5 - The nature of the game is revealed
Pete: I think it’s time I tell you what the game is about. If you haven’t guessed it already. It’s the game of Tic Tac Toe.
Darline: What? No way! I would never have guessed that!
Ok, just kidding.
Pete: I know. It probably was obvious when I said players place tokens on a board by entering an index for a field. But then… No, it could also have been the game of checkers, for example. But it’s just Tic Tac Toe. I thought we start with something small and see how it goes.
Darline: Good idea to start with something small. That way we have a chance “to get into the groove”. So, what’s your next request? Your wish is my command. Tiny wish, that is.
Pete: I’d the the game board to be displayed instead of the list of field indexes. Show the players the usual 2D board with crosses and naughts. “X” for the first player, “O” for the second player.
Darline: Sure. That’s very simple. Everything’s in place for that already.
[Darline thinks and codes for a little while…]
Darline: How do you like this?
The current state of the game board is rendered after each move. You see where the players put their tokens.
Pete: Wow! I like it. It’s looking like the real game now.
Darline: Yes, the 2D visualization really make a difference. It’s much more tangible now. Before it was more like playing blind.
Pete: Exactly! But since you said I should only make tiny wishes I did not dare to ask for the game board earlier. But now it was kind of inevitable.
Darline: Yes, the time was right. It could have been an earlier request, but now was ok, too. Nothing is lost. Right to the contrary: it was easy given what was in place already.
Where do you want to go from here?
Increment 6 - Constraining moves
Pete: A game is about rules. So far there are hardly any: players place tokens in turn on a 2D game board. That’s more like a physical limitation than a rule.
So here comes a real game rule. It’s constraining where players can place their tokens. The rule is: Players can only place tokens on fields not yet occupied by a token.
Darline: Makes sense. And of course I know this rule of Tic Tac Toe. But let me continue to play dumb.
It’s a straightforward easy to check rule. But what do you want to happen if a player tries to place token on an already occupied field? Should she lose the game right away because of a rule violation or be allowed to try again?
Pete: The player should be able to try again. Let’s keep it simple for now.
Darline: Good idea. Let me see how I can implement this.
[Darline thinks and codes for a little while…]
Darline: Here you go! That was an easy one. Check out how the player is kept in a loop to enter the index of a free field.
Pete: Looking great! Thanks. Yes, that was quick.
Increment 7 - Determining a winner
Darline: May I now ask for a feature?
Pete: Sure. Go ahead. What do you have in mind?
Darline: I’d like to remove the random decision to end the game. How about we start with part of the real rules to determine a win?
Pete: Yes, why not. I had a different baby step in mind. But we can do this first, if you like.
Here’s a first slice of the rules to determine a win: A player wins if she manages to put her token in all fields of one row. Examples:
Player 1 wins if fields 0,1,2 are all filled with an X.
Player 2 wins if fields 3,4,5 or 6,7,8 are filled with an O.
Darline: I remember that rule. Yes, let’s start with that. It’s to be checked after each move. Has a winning configuration of tokens been reached?
Let me see…
[Darline thinks and codes for a little while…]
Darline: Congratulations! You won, Pete! At least in this example game.
You really outsmarted me.
Pete: No, not really. You lost on purpose. You did not put up a fight.
But this is working great! It’s cool to see real game rules manifest in a tangible way. And you came around with the solution real fast.
Darline: It was easy to implement it. I knew exactly where to add the rule to check if any rows was taken by a single player.
Pete: Impressive. Thank you! How do you want to procede? May I again utter a request?
Darline: Sure! Go ahead!
Increment 8 - Full game over rules
Pete: How about implementing the remaining rules for ending a game? They are very similar to the one you just did.
A player wins if she manages to fill a column of fields: 0,3,6 or 1,4,7 or 2,5,8.
A player winds if she manages to fill a diagonal of the board. That would be fields 0,4,8 or 2,4,6.
You said it was easy to implement the first winning rule. Maybe these are easy, too.
Darline: That’s not baby steps anymore, Pete. It’s toddler steps. But I think the pattern is clear and it should be easy. I like your systematic thinking. It’s really just a couple of indexes that’s needed to check for a win. Maybe I can generalize my previous win situation detection.
I am feeling optimistic, so let me throw in as a bonus also checking for a draw. I imagine that’s easy, too: Once all fields are occupied, but no win was achieved, the game is a draw. Right?
Pete: Yes, that’s right. If you could do that, too, I’d be very happy. But only if it does not take you very long. I like the quick turnarounds. Seeing small improvements frequently feels great. It keeps my energy high — and makes me want more.
Darline: That’s how it’s supposed to be, Pete! I am glad you’re feeling this. And I can assure you, it’s great fun for me, too. It almost creates an addiction: I want to do the next feature and the next. Keep up the flow of features. So cool.
Ok, let me get to finishing the end of game detection.
[Darline thinks and codes for a little while…]
Darline: That was even easier than I thought! I am really happy well I could build on top of the previous solution. Check this out, Pete.
You won by filling a column. You won by filling a diagonal.
Pete: Great! Yes, that’s how it’s supposed to be. That’s all the winning configurations: a row or a column or a diagonal filled with the same player’s tokens. Thank you!
Darline: But wait, there is also the draw condition. Once all fields are filled without a winner it’s a draw. Look.
Pete: Yes! That’s the final game over condition. Well done! I am impressed by how fast you were able to do it. Amazing! I am very happy with the game. It will be fun to play with my kids.
Increment 9 - Tying up a loose end
Darline: It’s a working game, I think so, too. But from my professional point of view there is something missing. I’d like to do one more round.
Pete: Yes, sure. What is it? It’s working for me.
Darline: It’s working because of the user interface. Once a game is over, it’s over. The program ends. Players cannot move anymore. But internally that’s not the case. Theoretically moves could be made even after the game was finished. I’d like to tie up at least that loose end.
Pete: Ok, go ahead. I am sure it’s a piece of cake for you.
Darline: Yes, not a big deal.
[Darline thinks and codes for a little while…]
Darline: Done. Sorry for the little detour. But I am feeling better now.
You won’t see a difference in while playing the game, though. It was just a change under the hood for completeness’ sake.
Increment 10 - An unexpected feature
Pete: No problem. It was again quick.
But it gave me time to think. And I got one more idea. I’d like to go beyond the usual Tic Tac Toe rules. You’ve implemented them already.
Here’s my idea: If a player attempts an invalid move twice in a row, the player changes. For example:
I place my token on field 2.
You try to place it on 2, too. It’s an invalid move, but you’re allowed to place your token again.
You don’t watch the error messages and choose field 2 once more. It’s still invalid. It’s your second attempt with an invalid move. You’re not allowed to place your token again. I become the current player.
How does that sound? Doable?
Darline: That’s an interesting twist. I don’t think it really would come to that, but why not? It’s a fun addition to the game. And it seems to be a baby step.
You say: The player switches if one tries an invalid move twice in a row. It’s not twice over the course of a game, but just twice in a row. Right?
Pete: Correct.
Darline: Ok, let me try…
[Darline thinks and codes for a little while…]
Darline: This was a little bit of a challenge, but I managed to implement your request. Let’s say compared to the other features it was and older baby’s step. Check it out.
You see, I made two invalid moves right after another and the game switched to you as the current player. That what you wanted?
Pete: Precisely! Great! This is what I had in mind. A little twist to the regular Tic Tac Toe rules. I like it.
Thank you, Darline, for your help! I think I am good for now. Please wrap up the application for me to take home. I’m curious to see what my family will say about it.
Darline: Perfect! It was a pleasure. Thank you for your trust in my unusual approach. I’ll bundle up the code and send it to you.
But how about a coffee first to celebrate our accomplishment?
Pete: Great idea! I won’t say no to that.
By the way, did you know…
[Pete and Darline drifting into a more private conversation.]
Conclusion
What a ride! Thanks for staying on board.
Did you get a feeling for small and surprising Agile increments can be? Darline was never phased by Pete’s request. She always managed to implement them within a couple of minutes. She even encourage Pete to slice his requirements as thinly as possible and don’t tell him more than absolutely necessary.
Why was she able to deliver so quickly on requirements without a bigger picture? She never explored Pete’s domain comprehensively. She acted not like an engineer, but like a fighter reacting to punches thrown at her. Think of Trinity in “The Matrix”.
Of course I am not recommending to approach bigger projects in such an extreme way. No, take some time to explore the requirements together with domain experts. Get a bigger picture. Do some planning up-front — but don’t elevate your plan to dogma.
Nevertheless I think this is a valuable demonstration of a basic principle: Work in small increments and never assume you actually know a lot. There is always some strange special case or new idea around the corner threatening to throw off your best laid plans. Always ask: Can we slice the requirements more thinly? Can we reduce the scope a bit more, break up a big feature into multiple small features?
Don’t try to build a comprehensive domain model with intricate objects. It’s going to be a bottle neck for cooperation between different developers and couples features more tightly than necessary.
In a follow-up article I’ll show you what Darline’s code looks like. You won’t find an object domain model there. That’s not a bug, but feature of her code base. She did that intentionally to stay maximally open to Pete’s request all the time.
And you’ll see how Event Sourcing supported her approach.
So far this was an example for interactions with a customer. The follow-up will look under the hood and be an example of mapping requirement increments to code.
Stay tuned…
Incremental Event Sourcing - Under the hood
Remember how Darline implemented the game of Tic Tac Toe for Pete without knowing what the application was about for a long time? I documented their interactions in this post: