Java Forum Nord 2016 - tdlcr - Test Driven Legacy Code Refactoring by Falk Sippach

This article is part of a series about Java Forum Nord 2016, a conference that took place in Hannover, Germany. Links to articles about other talks I visited there can be found below.

I visited Falk Sippachs great talk about how to handle legacy code last year (see my article here) as well as the updated version this year. There have been many parallels, but also new topics. In this article, I’m going to point out only new thoughts in comparison to what Falks presented last year.

What also lured me into his talk, was the title “Test Driven Legacy Code Refactoring”. I think that’s a great title. Often, I see refactoring without any test, not even manual smoke tests. This is very dangerous and I’ve seen many situations where this behavior introduced new bugs into the system. Tests have to be written to prevent that. However, tests are not written at the time the implementation gets written. Then, they have to be introduced later, which is way more difficult.

Right at the beginning, Falk mentioned that the own code can turn into legacy code very fast. I agree: Often, I ask my fellow developers “Are we able to understand this in 6 months?”

The mentioned “Edit and Pray” strategy, just inserting your changes and pray they don’t break anything, is not so great. We need what Falk calls a “Canary in the coal mine”: A system that tells us that our changes are somehow wrong and break things. That is why we need to introduce a safety net, for example the Golden Master technique.

With this insurance in place, we can add new functionality by using TDD (Test Driven Development). It’s important to add new functionality only with tests! Otherwise, the changes would further break the codebase by making it even bigger and harder to test. From my own experiences I know that this is really hard. Often, after long debugging hours finally revealed what to change, the exhausted developer just wants to get the job done and doesn’t bother to write tests. Been there, did that. Always felt guilty about that and always regretted it later on when my changes spawned new bugs.

Falk went on talking about Sprout Methods. This concept was originally mentioned by Michael Feathers and basically means adding new functionality in a way that is easy to test. New code is often added by implementing new methods that are (hopefully) developed using TDD. Falk gave a nice, easy and step by step example of this.

Speaking of TDD, Falk suggested to take really small steps instead of doing multiple things in parallel. I agree to this “baby steps” concept. I force myself (and the participants of coderetreats I facilitate) to only change a tiny bit, then commit the changes into source control, then go on with the next baby step. This behavior lowered my stress level significantly.

Of course, there is always existing code that has to be tested. This is often very cumbersome and expensive. Falk explained the concept of “subclass and override” and why it’s wise to extract pure functions from existing code. Pure functions are often smaller and easier to understand than their regular counterparts. That is the reason why they are also easier to test.

There are many more techniques in Michael Feathers Book “Working effectively with Legacy Code”.

As tool support, Falk showed how to automate the comparison between the Golden Master and the current output with the library approval test.

Here are Falks slides.

Other Content of Java Forum Nord 2016

These are the talks I visited:

  • Keynote by Uwe Friedrichsen
  • Thymeleaf, a template engine for developers and designer by Gerrit Meyer
  • Test driven legacy code refactoring by Falk Sippach
  • What every developer should know about Strings by Bernd Müller
  • Code reviews, techniques and tipps by Rabea Gransberger
  • Requirements are always to blame by Frank Düsterbeck
  • Communication as impediment by Rüdiger Schnirring

TL;DR

At Java Forum Nord 2016, Falk Sippach talked about how to change legacy code by using the Golden Master technique, TDD, sprout methods baby steps, “subclass and override” and pure functions.