Working Effectively with Legacy Code
Is your code easy to change? Can you get nearly instantaneous feedback when you do change it? Do you understand it? If the answer to any of these questions is no, you have legacy code, and it is draining time and money away from your development efforts.
In this book, Michael Feathers offers start-to-finish strategies for working more effectively with large, untested legacy code bases. This book draws on material Michael created for his renowned Object Mentor seminars: techniques Michael has used in mentoring to help hundreds of developers, technical managers, and testers bring their legacy systems under control.
The topics covered include:
- Understanding the mechanics of software change: adding features, fixing bugs, improving design, optimizing performance
- Getting legacy code into a test harness
- Writing tests that protect you against introducing new problems
- Techniques that can be used with any language or platform—with examples in Java, C++, C, and C#
- Accurately identifying where code changes need to be made
- Coping with legacy systems that aren't object-oriented
- Handling applications that don't seem to have any structure
This book also includes a catalog of twenty-four dependency-breaking techniques that help you work with program elements in isolation and make safer changes.
Review By: Cathy Bell
02/02/2011A quick peak inside most organizations today would find legacy code running some crucial piece of their system. You can almost hear the code scream as you view the source, "I've been running this way for years. Why change now?"
So why did Michael Feathers decide it was time for Working Effectively with Legacy Code? He knows of the struggles many of us face when changing legacy code because he has experienced the same and has compared notes with others who have had similar experiences. His mission is to change our view of legacy code.
Working Effectively with Legacy Code gives us techniques to help us understand legacy code, get it under test, refactor (improve design without changing behavior), and add features that will enhance our ability to make changes to legacy code in the future.
This book includes three sections: the mechanics of change, changing software, and dependency breaking techniques, plus an appendix and glossary. The first section introduces the reasons for change, how to implement changes, and introduces concepts utilized in the other sections. The author covers unit testing, a test harness, the legacy code change algorithm, the seam model, and the tools available to help ease the changes in legacy code.
Chapters in the second section each begin with a question about changing code. The chapter then presents the material in a "Frequently Asked Questions" format, listing examples of the changes required as well as advantages and disadvantages to the various methods proposed. Included in this section as well are examples of how to implement Test Driven Development, reasoning about effects, and tackling monster methods.
The third section covers dependency breaking techniques that are meant to allow you to isolate sections of your legacy code making it safer to install changes. First, the techniques are explained with examples to bring the idea into focus and then the steps to create these techniques in your own code are given. The appendix discusses the extract method of refactoring only to give us a "flavor of the mechanics involved in refactoring with tests."
This book contains easy-to-read, realistic, practical advice. The reader should understand that the sections of code are only partial examples, but they superbly exemplify the author’s point. The author’s humorous approach to stressful situations that cause us tremendous stress adds value to the book, making it more than just a reference tool. The book would be helpful to new programmers before they make changes to legacy code. If you want to explore a particular section in more depth, the author cites works from various experts. This book is a valuable tool in that the author has done the research and knows which books will answer specific questions.
There are probably only a handful of businesses that disagree that legacy code is a drain on their development resources, thus responsible for a big chunk of their budget. Even code that runs smoothly is not immune from hardware or system upgrades. Inevitably something in the code needs to be changed when portions of the same system change. According to Michael Feathers, legacy code is "code without tests" and cautions that attempting to make changes to such code, even clean code, without tests is "like doing aerial gymnastics without a net." This book explains how to put the safety net in place when changing legacy code.