I don’t think Working With Legacy Code gets the respect and readership that it should. I believe that’s because most of us have a working definition of legacy code that implies something we want to avoid: We want to work on the cool new stuff, not the old legacy stuff. It makes us conjure images of C, or FORTRAN, or worse, COBOL. Or maybe something newer, but still mature enough you want to move on.
That’s not the definition Michael uses in his book. Michael defines legacy code as “Code without tests”. Based on that definition, do you work on legacy code? If you’re honest, you’ll say yes. Now, ask yourself if you want better techniques to work with code that doesn’t have tests.
If so, this is for you. You’ll learn several specific techniques that you can employ to take this code, make the absolute minimum number of modifications to get the code testable, and then you’ll feel safer applying your usual refactoring techniques.
I like the way the book is organized, with lengthy chapter titles that point to specific large scale code problems you’ll often find in code that doesn’t have tests. Example titles are “My Application has no Structure”, or “I can’t get this Class into a Test Harness”. Do those sound like problems you encounter? In these and other chapters, Michael identifies several common practices that lead to untestable code: dependencies on other system resources, unavailability of public interfaces to support testing, lack of interfaces for mocking, and so on. Each chapter title is more or less a description of the current problem, and the chapter content is a set of techniques that will enable you to move that code into a more testable design Once you can apply tests, you can add those tests and then go about your changes.
Other chapters show how to write tests that help you understand the current behavior. While this can seem silly, it does help ensure you don’t make a mistakes as you move the code forward.
Final, the last section of the code is a set of techniques that help break dependencies between different parts of a legacy system so that it is easier to inject those tests.
I haven’t said anything about the languages used in the book for examples. That’s because there are several: C++, Java, and C# all appear. One section that is specific to moving from procedural to OO techniques includes C. However, if you use a different language, don’t let that turn you off. The techniques are language agnostic, and that is proven by mixing the samples in different sections with different languages.
This is one of those books hat will always be handy,and will be one of the resources I turn to often when I inherit that set of code that just doesn’t have any tests. If you find yourself staring at blocks of undecipherable code, you should do the same.
All of these projects are Open Source (using the Creative Commons license for content, and the MIT license for code). If you would like to contribute, visit our GitHub Repository. Or, if you have questions, comments, or ideas for improvement, please create an issue for us.