Chesterton's Fence & Refactoring
Working with legacy code is often challenging. Lack of tests, odd formatting, old technology and dead code. A good developer will desire to improve the code through refactoring. Refactoring often involves removing or replacing curious bits of code. And this is often where problems arise. In the timeless words of G.K. Chesterton:
“In the matter of reforming things, as distinct from deforming them, there is one plain and simple principle; a principle which will probably be called a paradox. There exists in such a case a certain institution or law; let us say, for the sake of simplicity, a fence or gate erected across a road. The more modern type of reformer goes gaily up to it and says, “I don’t see the use of this; let us clear it away.” To which the more intelligent type of reformer will do well to answer: “If you don’t see the use of it, I certainly won’t let you clear it away. Go away and think. Then, when you can come back and tell me that you do see the use of it, I may allow you to destroy it.”
It’s good to approach refactoring legacy code with a little humility. It’s likely that the software has been functioning as desired for over a decade. While the cleanliness of the code may be in question, its purpose is sound. Be careful when pulling bits of code that appear to have no execution path. These bits need diligent examination before removal.
One approach for refactoring legacy code is to add tests before refactoring. This will provide confidence that no critical bits got removed from the code. Writing good tests over legacy code involves a level of deep-thinking. By the time you have tests that cover the existing functionality, you’ll also have an idea of how to write a cleaner version. The other benefit is that you’ll be able to reuse your test cases for the new code you write.
If it is impossible to write tests for the code, be rigorous. Take the time needed to understand what’s going on. Read the code carefully, see if the comments appear relevant. Run the application and use the functionality for the bits needing refactored. Use the debugger and breakpoints. Often there is no substitute for debugging and stepping through odd bits of code. Seek out anyone in the organization that may know something about the functionality. Determine the use cases and write your new code with tests that fulfil the use cases. As you discover new use cases, add a representative test case.
There is an immense joy that comes from deleting nasty bits of code. Be sure you know its intent, or there could be a long path of suffering ahead.