1st Darmstädter Legacy Code Retreat 1


In the beginning of this year, I decided to organize a code retreat. A little later Simone Bächle pointed me at jbrains’ lovely example of a messed up trivia-game implementation and the idea of a Legacy Code Retreat. I quickly decided to give the concept a try and that’s how the 1st Darmstädter Legacy Code Retreat came to be.

What’s a Legacy Code Retreat?

We’ll, the idea is easy: Give some developers some terrible piece of code and make them try clean it up. Clean up, of course, starts with tests and continues with systematic refactoring. The format is quite similar to “traditional” code retreats. The day is divided into multiple sessions (each about an hour), where participants pair and solve a specific task. After each session the code is deleted, all participants join for a short retrospective, and than regroup for the next session.

Preparations

Everything starts with some preparation… For me it started with finding a sponsor for the event, which was surprisingly easy, as andrena objects was more than willing to jump in. Thank you very much! I booked a small lecture hall at my University, which solved the room issue. Not the ideal solution, as walking around and working in small teams is difficult in a lecture hall, but it worked well enough. Getting sufficiently many power plucks into the room was an issue though…

Promotion and registration were organized by the Java User Group Darmstadt. I did some additional promotion in lectures and forums to attract students to the event. This led to 30 registrations, 18 of which actually showed up in the end. I guess that’s a pretty good ratio for a free event that starts on a Saturday morning 😉

For those interested, this is the list of foods and drinks used up during the event:

  • Coca Cola – 1 box
  • Apple spritzer – 2 bottles
  • Fanta – 5 bottles
  • Water – 1 box
  • Coffee – about 25 cups
  • Milk – 250ml
  • Lump sugar – less than 10 pieces
  • Bananas – 1.5kg
  • Apples – maybe 2? xD
  • Grapes – 2kg
  • Pieces from the bakery (sweet:salty – 2:1) – 40
  • Party pizzas (40cm x 60cm) – 4

I decided for 6 sessions during the day, each of which started with a short intro to the session task, followed by 45 minutes coding time for the pairs, and closed by a 10 minute retrospective with everybody.

Session 1: Get to Know the Code

The first session was all about getting into the code. I did not explain what the code is about. Participants paired, checked out a copy of the code from GitHub (did you know you can checkout parts of a GitHub repository using SVN?) in a programming language of their choice and got going. Participants found that it was better if they chose a language they were already familiar with, since setting up the tooling and thinking oneself into a new/unfamiliar language took too much time to get started with the actual legacy mess.

I allowed the groups to change the code, if they wanted, but under the condition that they don’t change any untested code. This led to some groups trying to cover the whole thing with tests before touching any code. None of them even remotely finished within the coding time.

Session 2: Golden Master

The second session was about the Golden Master technique. There’s a great post by jbrains about Golden Master, in case you don’t know it yet. At first, I was afraid that the task is too narrow and that all teams would end up doing almost the same, but in the end I was amazed about how many different techniques the participants came up with. All teams managed to create a Golden Master and most managed to automate comparison of the current execution output against their master.

Many participants stated they weren’t familiar with the technique before. They quite liked the idea, though some were sceptical as to the scalability of the approach. We spent some time of the retrospective to sketch how one could break down a larger system and apply Golden Master to the parts separately. We also found that it’s sometimes difficult to randomly generate inputs for applications.

I allowed teams to keep their master for the remaining sessions and to use it, if they wanted to.

Session 3: Subclass to Test

This was a surprisingly difficult one. Though all participants got the general idea of subclass to test immediately, most had difficulties applying the technique to the trivia code. The mental model of the technique (somehow getting rid of an external dependency, like a database) didn’t match the problem at hand, ad the trivia game has no external dependencies.

I spent much time during the session going around and talking to the pairs. I think next time I will spend some more time explaining the technique on a more abstract level. In the end, it’s not limited to getting rid of dependencies. You can use it to separate functionality and get rid of some of it, so as to focus testing on what remains. If you focus on the roll() method, for example, you could factor to something like this:

public void roll(int roll) {
    System.out.println(players.get(currentPlayer) + " is the current player");
    System.out.println("They have rolled a " + roll);

    if (inPenaltyBox[currentPlayer]) {
        handleMoveFromPenaltyBox();
    } else {
        handleNormalMove();
    }
}

Then you can override handleMoveFromPenaltyBox() and handleNormalMove() with empty methods to test only that both cases are properly separated. Then you could go for the extracted methods separately, to test the respective cases in isolation. This requires us to raise the visibility of the extracted methods. We had some discussion about whether this is a valid move or not in the retrospective, which came from people feeling uneasy with opening internal functionality to the outer world. I think it’s important to keep in mind that were doing this to bring the code under control and change it. What’s going to be exposed in the end might change in the process and as long as you don’t release it, it’s not a problem. If you release some intermediate state (even internally) you should probably mark the respective methods @Obsolete with a respective comment. If there’s language features like .Net’s friend assemblies that can help you keep things private and still test them, it’s probably a good idea to use them.

Session 4: Extract Pure Functions

This was the first session taking the focus away from testing towards refactoring. Placing this after the lunch break worked fine, because the testing ideas had some time to sink in.

The idea of extract pure functions is extensively explained in this post by Adrian Bolboaca. The session worked quite well and people said they felt very productive actually changing the production code this time, instead of beating about the bush with tests. Funnily, many reported at the same time that they actually got less things done in this session.

In the retrospective I learned that some groups had thrown testing over board. When asked, they admitted that they had really no idea if their code was still working, even though they worked with baby steps. I’m not sure if it makes sense to force testing in this session, because maybe the coding time is too short to do both testing and exploring the refactoring strategy. At the very least, one should do this decision consciously and bring it up with the whole group.

Session 5: Remove Duplication

I will drop this session, if I do another Legacy Code Retreat. For one, most pairs already worked on duplication throughout the previous sessions (especially in session 4). Moreover, 6 session turned out to be quite much for both the participants and myself. I think it makes sense to merge this session with the previous one.

Session 6: Make It Easy to Extend the Code

For the last session, I gave the participants two possible extension points:

  • Adding an additional category
  • Making the penalty rules exchangeable

Condition was that no untested code was changed (I added this in reaction to the feedback after session 4). Most groups focused on the categories, some worked on the rules, and some even managed to work on both. Some groups used their Golden Master from earlier on or created a new one. They then added unit tests for the respective parts and started refactoring.

Conclusions

For me, the event was a huge success and I learned a lot myself. As I stated before, I was a little scared that the tasks might be too narrow for people to experiment, but it turned out they really aren’t. 5 sessions is probably a good length and doesn’t hurt to have two mentors go around to discuss with the pairs. With 18 participants I managed on my own, but with more I wouldn’t have had the time to talk to all of them within the coding time.

Thanks to all participants for making this a great event! Thanks also to jbrains for coming up with this whole concept and for helpful hints, and Adrian Bolboaca and MonospacedMonologues for their posts. I loved the day, and I hope to run another (Legacy) Code Retreat soon.


Share this: Facebooktwittergoogle_plusredditpinterestlinkedinmail | Follow me: twittergoogle_plusyoutube