12 Working with legacy code

 

This chapter covers

  • Examining common problems with legacy code
  • Deciding where to begin writing tests

I once consulted for a large development shop that produced billing software. They had over 10,000 developers and mixed .NET, Java, and C++ in products, subproducts, and intertwined projects. The software had existed in one form or another for over five years, and most of the developers were tasked with maintaining and building on top of existing functionality.

My job was to help several divisions (using all languages) learn TDD techniques. For about 90% of the developers I worked with, this never became a reality for several reasons, some of which were a result of legacy code:

  • It was difficult to write tests against existing code.
  • It was next to impossible to refactor the existing code (or there wasn’t enough time to do it).
  • Some people didn’t want to change their designs.
  • Tooling (or a lack of tooling) was getting in the way.
  • It was difficult to determine where to begin.

Anyone who’s ever tried to add tests to an existing system knows that most such systems are almost impossible to write tests for. They were usually written without proper places (called seams) in the software to allow extensions or replacements to existing components.

There are two problems that need to be addressed when dealing with legacy code:

12.1 Where do you start adding tests?

12.2 Choosing a selection strategy

12.2.1 Pros and cons of the easy-first strategy

12.2.2 Pros and cons of the hard-first strategy

12.3 Writing integration tests before refactoring

12.3.1 Read Michael Feathers’ book on legacy code

12.3.2 Use CodeScene to investigate your production code

Summary