Our take on Global Day of Coderetreat 2023
November 09, 2023
Coderetreat is a day-long workshop focused on sharpening software development skills. There are different forms and flavors, but usually you use Pair-Programming and Test Driven-Development to implement Conway’s Game of Life and delete your code at the end of each session.
Some benefits it can bring to your team:
- Practice TDD, Pair-Programming, and other eXtreme Programming techniques the team might use in the future.
- Knowing IDEs, keyboard shortcuts, testing frameworks, and libraries better.
- Work with folks you don’t work with daily.
- Egoless programming - removing your code at the end of each session is a great way to practice it.
- A nice break from your daily business-driven work, technical debt, and “getting things done” - you focus more on the road than a goal.
How to organize it?
We had some experience with participating in Coderetreats, but we never organized one. Because of that, we decided to run an internal-only session, without much advertising and limited just to the Polish branch of our company and with just 4 sessions.
The Workshop, Hosting Guide, Facilitation Guide and Constraints articles all contain great hints on how to organize, prepare sessions, etc., but we started one step back by creating an online spreadsheet to allow anyone to put their name with some details on
- preferred and secondary programming language,
- online vs. office participation,
- preferred communication language,
- additional comments (food preference, other programming languages, etc.).
Thanks to that, we could assess what kind of sessions we could run, how big of a room we needed, how much food, etc. Following the No Pizza Rule we ordered sandwiches and sushi according to the number of in-office participants.
We also created a simple starter pack to hint participants what to check before the workshop (IDE plugins, microphone, TDD starters, etc.).
How to run it?
Thanks to the small number of participants (4 in the office, 4 online with 5 and 3 planned initially), we created a more inclusive atmosphere. Literally, everyone said a couple of words of introduction, and each session ended up with a retrospective where we talked individually. With a bigger group, we could run in-pair retrospectives and end up with a summary or more open discussion, but it would be very limited in time.
In our case, pairs were chosen a day before, in order not to waste workshop time. We wanted everyone to code online at least once (as it’s close to the nature of our work), but we also wanted everyone to utilize office space and have first pairs sitting next to each other when possible. We also assigned based on preferred and secondary programming languages.
We used the following slides: mat3e.github.io/talks/coderetreat/en and the schedule as follows:
- Introduction [15m]
- Everyone said a couple of words about themselves.
- Goals of Coderetreat.
- Pair-Programming explained.
- TDD explanation and contrasted with higher-level tests.
- Game of Life explained.
- Session 1 [45m] - no restrictions, just giving it a try.
- Retrospective 1 [15m] - thoughts, especially on deleting the code.
- Session 2 [45m] - no mouse time, focusing on keyboard shortcuts.
- Retrospective 2 [15m] - thoughts, especially which keyboard shortcuts you learned.
- Lunch break [30m] - No Pizza Rule :)
- Session 3 [45m] - using secondary programming languages.
- Retrospective 3 [15m] - thoughts, especially if you plan to use the same language in the next session.
- Session 4 [45m] - developing within 5-min deadlines (called Baby Steps here).
- The Closing Circle [15m] - observations about the last session and 3 questions:
- What did you learn today?
- What surprised you today?
- What will you apply starting Monday?
Each of the sessions provided me with valuable insights and learning experiences.
In our first session, my colleague, who works primarily with Kotlin daily, and I embarked on solving the Game of Life problem in Kotlin. Our initial focus was to create an elegant API based on multiline strings that could eventually support emojis and generate aesthetically pleasing output with each generation of the game. We began with input data validation, aiming to write idiomatic Kotlin code. Surprisingly, we got caught up in this aspect and didn’t even start implementing the algorithm during the session. Nevertheless, I had a great time recalling the syntax peculiarities of Kotlin, as I mainly work with Java in my daily tasks. On the other hand, we learned that it might be wiser to dive into the algorithm initially instead of refining the API. Towards the end, the decision to discard all the work was not mine alone, but it was a somewhat painful but necessary step to adhere to the egoless approach, as highlighted in Greg Young’s well-known presentation, ‘The art of destroying software’.
With this approach in mind, we entered the second session, revisiting the Java environment with the added
challenge of not using a mouse. Fortunately, this was a minor challenge for me, as I had previously explored
keyboard-centric work techniques with a colleague at a previous job. It resulted in numerous feature requests to
JetBrains for missing keyboard shortcuts and installing the Vimium plugin in our web browsers. While I have
become less dogmatic about such matters over time, it still bothers me that specific actions, like submitting a pull
request to GitHub via a JetBrains plugin cannot be accomplished solely with the keyboard. Returning to the session, I
realized that I had forgotten the keyboard shortcut for setting breakpoints (
⌘ + F8) and for launching the
⌃ + ⌥ + D). Code With Me, unfortunately, lacks shortcuts for switching between modes like follow or pair
coding mode. We acknowledged that using the debugger is considered an antipattern, but we decided to explore it using
only keyboard input since it’s a tool we rely on daily. Regrettably, we still couldn’t solve the exercise
due to a simple mistake. Nonetheless, we had an enjoyable time. While practicing TDD in Ping-Pong style, we broke the
convention by altering our approach during an extended implementation. This highlighted the importance of not letting
iterations become overly prolonged. When making such changes, it’s beneficial to consult with your
partner empathetically to ensure it aligns with their preferences, fostering mutual respect and trust. It’s essential
to remain open to alternative approaches and not forcefully impose your own. During the implementation phase, we devised
a more straightforward test case idea to test the entire algorithm behaviorally.
In the third session, we returned to Kotlin, and the knowledge gained in the previous two sessions proved valuable for
both my new partner and me. We immediately approached the problem from an algorithmic perspective, leaving the polished
API for the end. However, this time, it was more challenging, as neither of us primarily programmed in Kotlin.
Everything was progressing well until we encountered an error. Instead of debugging, my partner convinced me to add
logs, which proved invaluable in identifying the issue. I found this experience refreshing, as I seldom employ this
technique daily. GitHub Copilot was a significant help when adding logs, making the process quick and
efficient. Unfortunately, the primary issue remained elusive. We tried using the debugger but to no avail. After
thorough code analysis, we discovered we were building a new state based on a shallow copy of the previous one.
Unfortunately, Kotlin’s arrays only have a
.copyOf() method and lack a
.deepCopyOf() equivalent. Once we identified
this error, the entire Game of Life algorithm worked as intended, though time constraints prevented us from refining the
This set the stage for my plan in the fourth session. In this round, we aimed to elevate the standards of egoless
coding. We followed a TDD pair-coding Ping-Pong approach, with each round limited to five minutes for writing tests,
code, and refactoring before committing our changes. Exceeding the time limit meant erasing everything. The
exciting part was that this was the final session, and drawing from our experience in the previous sessions, we had
plenty of creative ideas to tackle the challenge. Despite this, we faltered while attempting to implement one of the
simplest behavioral tests:
111. It’s a single row with three living cells that should transition to
010 in the next
iteration. Achieving this in five minutes is not straightforward, and mistakes can easily creep in. Therefore, we
bent the rules slightly, taking advantage of our Code With Me setup. We divided the tasks and independently
implemented different parts of the algorithm simultaneously. This approach allowed us to meet the deadline. Without this
approach, we would have introduced code smells. We would have exposed the implementation details in tests, which must be
clarified for users. Consequently, we would have needed to return to behavioral tests covering all aspects of
the algorithm, remove implementation detail tests, and ultimately close access to those details. This approach prevented
us from cementing our code with unnecessary redundancy while maintaining a minimal set of tests. Thankfully, it worked.
Unfortunately, time constraints once again prevented us from refining the API.
In summary, these sessions were a fantastic learning experience. Each one enabled me to acquire new knowledge and refresh my understanding of concepts I don’t encounter daily. Furthermore, they allowed me to collaborate with colleagues from different teams, fostering knowledge transfer and mutual support. My peers share a similar perspective on these sessions.
The Closing Circle of the article :)
Participants were happy with the workshop, and we got more positive feedback. Next time, we plan to run a full-day workshop and probably pair with other offices.
Furthermore, as we already cooperate with Warsaw Java User Group and WarsawJS (they run their meetups in our office), we are considering a public Coderetreat next year, perhaps in cooperation with both groups.