Last week I’ve participated in a Global Day of Coderetreat organised by the London Software Craftsmanship Community and hosted by Masabi. It was a ton of fun, I got to meet loads of like-minded people and participate in the fun of writing code together. But let’s not get ahead of ourselves. On the off-chance you don’t know:
Coderetreat? What’s that?
It is a day long event, where developers get together and engage in structured work on code. The day is split into multiple sessions, with short breaks in between. In the beginning of the day the whole group is given a problem - Conway’s Game of Life. Then, for each session they are presented with a set of restrictions. The group splits into pairs that work on their solutions using TDD and adhering to the restrictions.
Each session lasts forty five minutes and there is no expectation that the problem will be solved by the end of it. When the forty five minutes run out - all the code written gets deleted, notes destroyed. The pairs share their experiences with the rest of the group.
Then the next set of restrictions gets presented, participants split up into new pairs and get to work.
The day usually consists of 5-6 sessions like that.
If you’re craving more information - have a link.
Conway’s Game of Life? What’s that?
If you didn’t feel like clicking one of the links above, here’s a quick summation of what this Game of Life thing is all about.
You have a board, the board is conceptually infinite and consists of cells. The cells can be either alive or dead. They behave according to four simple rules:
- If a live cell has fewer than two neighbours that are alive - it dies (under-population);
- If a live cell has two or three alive neighbours - it survives;
- If a live cell has more than three neighbours that are alive - it dies (over-population);
- A dead cell with exactly three alive neighbours becomes a live cell (reproduction).
The initial pattern of live and dead cells is provided as input, then the system does its own thing by applying the four rules at every tick of the game clock.
The really neat thing about this is that these four simple rules result in emergence of patterns: some static, some moving around the board, some with pretty complex behaviour. If you haven’t checked out the Wikipedia link above, I heavily recommend you take a look at the ‘Example of Patterns’ sub-section.
You can also give it a try here. If you’re not sure where to start - try this pattern:
The Actual Day? What’s that?
So for us the event was split up into six sessions, with an hour and a half break in the middle for lunch (with delicious veggie stroganoff, veggie lasagne and some other irrelevant food).
Approach the problem however you want.
I teamed up with Dinis and we gave it a tackle using CoffeeScript, setting up a unit testing framework first. We started, pretty much, by creating a Cell object with x and y coordinates inside and a boolean to depict whether it was alive or not. Had some discussions about the infinite grid and then the time ran out. I think that was a good way to introduce the problem to us - allow us to poke it with a stick on our own.
We could only use primitives, objects were not allowed, methods were not allowed either (except for the main method in Java and test methods).
I paired up with Chris and we chose to use Java, and rather than write tests using an existing framework decided to go simple and create ad hoc methods that would do our tests and return true or false depending on whether the test has passed. We then stuck those all over the place in our main method, instantiated the board, created a ce… Then we ran out of time. Not having objects is hard.
We could only use objects. Methods couldn’t return or accept primitives.
Paired up with Hawazine and we intentionally picked a language I didn’t know, and she hasn’t used for a while - Kotlin! So with docs open in one window and IDE in another, a sheet of paper in front of us - we gave that ago, deciding that wrapping primitives inside objects would be cheating. So we worked under the assumption that a cell’s position on the grid can be defined by its position in a list of cells. We had a Cell class, as well as DeadCell and LiveCell that extended Cell. And a Board object. Then we ran out of time. Not having primitives is hard.
We had to take the functional programming approach. Objects are immutable.
Shane and I attacked the problem through the magic of C++, creating a shiny new instance of the grid with a new and updated state whenever it needed changing. We focused our testing on the low-level aspects of the program and experienced an epiphany (heavily inspired by the event’s facilitators - Julian, Pawel, Chris) leading us to believe that our tests should focus on testing grid changes rather than the low-level stuff. When we were about to do that - we ran out of time.
In the fifth session every cell had to live in a separate thread. Bonus points if the cell is hexagonal.
Paired up with Janos and pair-programmed in good old Java. We kind of immediately decided to ignore the hexagonal bit of the requirement and just dove into writing all the stuff we needed for the threads to behave, occasionally swapping places in front of the laptop and also kind of forgetting about testing. Time ran out again.
The final session was a pen and paper exercise. Everything is a microservice. What would it look like, what tests would it need?
For this one Antonio and I went from a very minimal amount of microservices (2) to a stupidly huge number and then decided to settle on something in-between that also made sense. So it felt like the cleanest architecture would be:
- A Database sits in the middle.
- SeedService generates the initial state of the grid and sends it to the InputOutputService.
- IOService stores data in the DB.
- IOService fetches data from the DB and sends it to the RulesService.
- RulesService applies all the rules to the current grid, decides which cells die, which are born, and which remain in their current state.
- RulesService sends the data back to the IOService.
- IOService stores the data in the DB.
- DisplayService fetches data from the DB and displays it to the user.
Boom, done! Had plenty of time for that one.
The whole event was a ridiculous amount of fun. Throughout the day we reached out to other developers participating in Global Coderetreat in other countries (Spain, Romania, etc) and discussed constraints we had and they shared the constraints they came across, and it was amazing to have this huge shared experience.
The format of the event is great, because without the expectation that you will complete the task by the end of the 45 minute session, without the code physically remaining on your machine - there is no pressure to complete anything no matter what, sacrificing the cleanness of the solution, or testing. You can make your code as good as you want it to be. And that is really, really cool.
It is always a pleasure to meet like-minded people that do what they do because they love coding and believe in a better way to do things. And after this experience I feel less naive when I talk about the need for clean code, clean architecture and good tests, because, guess what, there’s plenty of us who agree on that.