The first Coding Dojo I ever hosted was right before the whole team’s Christmas vacation. So I prepared some cookies, and some hot wine punch and invited everyone to help out our pal Santa Claus!
Santa has to work when all of us try to spend some quality time with our families: On Christmas Eve.
His job is always the same:
- Santa has to think of some good presents from memory.
- Santa has to pick one of his many ideas randomly.
- Santa has to buy that present from the mall.
- Santa has to deliver that present by car.
I gave the teams (pairs of two) a brief glimpse of Santa’s brain:
The teams now had around 15 minutes to code a console application that plots the following output:
The console output is not very convenient. As soon as Santa closes the application all information is lost.
As the one and only customer of our application he therefore wants the output to be written into a file. He wants to toggle that functionality via a command line argument.
The teams had another 15 minutes to implement that feature.
Some teams already heavily discussed their architecture, some teams took a very pragmatic approach, some teams went full quick-and-dirty consciously. So many different solutions for such a trivial task.
And not for the first time! Of course this influences Christmas Eve:
Santa can’t remember the presents from memory when he is drunk. He has to get his ideas from a file he created when he was sober:
Since we never know whether Santa will be drunk or sober on Christmas Eve, the team was instructed to create another command line argument to toggle that behavior: From memory when sober, from file when drunk.
The teams had another 15 minutes.
Deserializing the *.json file was a piece of cake. But the development of some teams already went a little sluggish. Especially the quick-and-dirty team had to fight with their own design decisions.
Every team moved one laptop to the right and was left with the code of their predecessors. It was like being the new guy in the team and looking at the big pile of legacy code.
They now had to implement the following new requirements in 25 minutes:
When Santa is drunk
- he does not care. He always picks the first present he finds in the file.
- he can’t walk to the mall. He just orders from Amazon.
- he can’t (and is not allowed to) drive by car! He just rides his reindeers. Old-school.
This is how the output should look afterwards:
All the teams immediately had a negative attitude towards the new code base. Just because it was unknown and yet to be read and understood. One of my colleagues even said when looking at the code of the quick-and-dirty-fraction:
I think we should continue implementing in that style…
This shows one of the main problems of code smells: They are contagious. When moving inside smelly code the inhibition level for writing bad code drops. The whole solution goes more and more messy. This is also known as the broken windows theory.
All teams admit that the exercise was not easy although it might look trivial. I asked them whether any of their solutions complied with the Open-Closed-Principle: None did.
So I presented them a solution that does. Thanks to the Strategy Pattern.
Take a look at the method
Run() . It is super easy to read. It represents our algorithm, our strategy. This is the procedure Santa does every year, no matter if drunk or sober. And the best part: This method stays untouched:
- Santa has to get his ideas from any kind of
- Santa has to somehow make a decision with a
- Santa has to buy the present from any
- Santa has to deliver the present with any type of
The strategy is very abstract. And that is the important part of this pattern:
- The strategy does not care whether the ideas come from memory, a file, the internet or his friends. It just needs the method
- The strategy does not care if Santa chooses randomly, the first, or the last present. It just needs the method
Present ChooseFrom(IEnumerable<Present> presents)from
- The strategy does not care if Santa buys the present in the mall, orders it from Amazon, from Ebay, or if he tinkers it himself. It just needs the method
void Buy(Present present)from
- The strategy does not care if Santa delivers by car, by reindeer, by foot or with a little help of UPS. It just needs the method
What happens on Christmas Eve always stays the same. Only how it is done changes from time to time.
Everything that stays the same is our strategy. This belong inside our class
Everything that can change, is injected into the class as dependency via the constructor.
That way we can decide how the strategy gets executed, simply by injecting the desired implementations.
That is all. That is the Strategy Pattern.
Short and snappy! Here are two examples:
- We create a new class, e.g.
- We let that class implement
- We give
ChristmasEvean instance of
- That’s it. We did not touch any old code. We only added new code. The Open-Closed-Principle approves.
It is all about identifying the strategy.
- What do you want to to? — Write things!
- Where do you want to write things? — I don’t care. I just want to write.
- Conclusion: All we need is an interface
IOutputwith a single method
That’s how two implementations could look like. Both are short and snappy. You see what the classes do without any scrolling.
Here is how our application root might look like:
I really like the solution. The Strategy Pattern really works well for this problem. All classes are small and read-able. We have the flexibility to react to further changes with ease.
Christmas is saved! Thanks for helping!
Somewhere it has to be done. At least that way it is in a single spot. You can swap the behaviors right here inside the root of your application instead of digging in the whole application.
And some smart people already solved that problem for you. If your root really gets too big to handle it might be time to have a look at IoC-Containers like Autofac.
Did you ever host a Coding Dojo? How were your experiences? Let me know! 🙂
Thanks for reading!