We should be refactoring the code we write and all the code that we encounter all the time. Making little improvements to code should be just something that developers do without even thinking about it.
I find that many of the anti-patterns the developers engage in when writing code are easy to spot and after I refactor code that uses those anti-patterns, I’m less apt to make the same mistakes in my code. This is the hidden benefit I found when I refactor existing code, it has made me a far better developer by teaching me not to use those anti-patterns in the code I write.
There is now a whole movement around people who like working with legacy code. They call themselves menders. In my experience, it’s about one in every 50 developers who like working in legacy code and these people really like it. There’s even a group and podcast called Legacy Code Rocks composed of self-proclaimed menders who prefer to remodel existing code over creating new code. Thank heavens there are people who like working with legacy code because most developers don’t and there’s a lot of legacy code out there that needs to be cleaned up.
When I write code, I try to think about the people who will come after me who have to look at my code and change it. I try to make things clear and sensible even if it requires a little extra effort on my part because I know how grateful I am when I have to maintain code when developers have taken the time to make their code understandable.
I find that the best time to improve a piece of code is in the moment while I’m looking at it. I may have gotten there in a debugging session or while I am learning a new piece of code but however I got there if I see an opportunity to improve code I want to take it and I want to encourage other developers to do the same. This should be part of our community of practice, that we are willing to go in and clean up code when it makes sense to do so.
Cleaning up code is not the hard part. The hard part is understanding the code and if software does what we need it to do then we don’t have to understand it most of the time. We only need to understand code if we need to change it.
So, I will make little changes to existing code all the time whenever I see an opportunity because it doesn’t take very long and I know that little changes can ultimately add up to significant improvements in code.
And when I say little changes I mean what we call the ‘safe refactorings’ like Rename Method or Move Method. These safe refactorings are typically used through an automated tool, like in many IDEs so there is little chance of making a mistake and introducing a defect.
But big changes, larger refactorings that could introduce defects, especially if the code is not under test, I reserve only for when I have sufficient justification. This might include needing to extend an existing system or add features to an existing system that doesn’t do something that I want it to do. If the system is poorly designed then I may have to take time and clean it up first. I often find that this is the most efficient way to add features to existing software.
In these situations, I use a technique called Refactoring to the Open-Closed where I first refactor the code to make space for the new feature and then add the new feature. I use this technique whenever I need to refactor an existing system and I also use this technique to emerge the design of a new system as I’m building it. In both cases, I’m simplifying the integration of new software into an existing system by first refactoring the existing code to easily accommodate the new feature.
Whenever I’m working in an existing system I’m typically doing two things, which is changing the existing code to make space for new features and then adding the new features. These are actually two distinctly different activities and I find that when I separate them out and do them at different times the process of working with legacy code becomes much more manageable and the opportunity to introduce defects becomes far less.
Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.
Previous Post: « Refactor to Retrofit Tests in Legacy Code
Next Post: Refactor to Redesign When You Know More »