Refactoring for dummiesPosted: September 2, 2004
Yes, I’m a refactoring dummy. Many moons ago, I was ranting about the constant need for engineers to refactor their code at work and got a homework assignment to read Refactoring: Improving the Design of Existing Code written by some fancy software engineer prof. Well, I’ve procrastinated my homework for well over a year now and need to get this book back to Nick. So, here’s what I learned.
Refactoring is risky. It requires changes to working code that can introduce subtle bugs. Refactoring, if not done properly, can set you back days, even weeks.
This has been my experience with big refactoring projects. Bugs, bugs, bugs. And that’s with top notch engineers doing the work. Now to be fair, that’s what QA’s for – – to find bugs, right? Sure. But I haven’t yet met an engineer that looked at another’s code and didn’t think they could do a better job writing it. While I believe that refactoring is certainly a necessity from time to time, refactoring for refactoring sake has never shown positives in my relatively short history in high tech. Refactoring to do something new, that’s the only time I’ve seen refactoring work out OK.
Refactoring is the process of changing a software system in such a way that it does not alter the external behaviour of the code yet improves its internal structure. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. In essence when you refactor you are imporving the design of the code after it has been written.
This is the crux of the problem with refactoring for me is that it can introduce NO new functionality. “Let’s clean up the code to make it easier to maintain.” I guess that’s a legitimate reason given maintenance costs at companies can be high. What’s more ideal in my mind is to launch some new incremental functionality and refactor in process. Kill two birds with one stone rather than just fixing software to reduce maintenance costs x%.
When you find you have to add a feature to a program, and the program’s code is not structured in a convenient way to add the feature, first refactor the program to make it easy to add the feature, then add the feature.
Now this sounds reasonable – – the author agrees with me! Maybe there’s something to refactoring. 🙂
Before you start refactoring, check that you have a solid suite of tests. These tests must be self-checking.
It looks like unit tests are critical part of the refactoring process. Since whatever you refactor you have to test, solid tests are critical to verifying you haven’t introduced new bugs. Nothing surprising here but I’ve seen even sr. software engineers ignore unit tests. “I don’t need tests because I’m a programming god and QA can pick up any bugs.” Ick.
When you use refactoring to develop software, you divide your time between two distinct activities: adding function and refactoring.
The author goes on to point out that when you’re adding new function, you shouldn’t be changing any existing code; you are just adding new capability. This is an interesting notion for me (not being a software engineer) because I always assumed that building something new required touching old code to make it possible to introduce new code. Maybe this is just a more theoretical statement versus something that happens in practice? In any event, adding new functionality seems to absolutely be part of refactoring. So, I’ve learned something new here. Refactoring doesn’t just mean massaging old code with nothing new attached to it. It could mean that, but it certainly isn’t the only meaning. Well this is positive.
In almost all cases, I’m opposed to setting aside time for refactoring. In my view refactoring is not an activity you set aside time to do. Refactoring is something you do all the time in little bursts. You don’t decide to refactor, you refactor because you want to do something else, and refactoring helps you do that other thing.
Amen brother! The refactoring god agrees with the basis of my rant. Refactoring for refactoring sake is wrong, wrong, wrong.
There are times when you should not refactor at all. The principle example is when you should rewrite from scratch instead. There are times when the existing code is such a mess that although you could refactor it, it would be easier to start from the beginning. This decision is not an easy one to make, and I admit that I don’t really have good guidelines for it.
Here I come back to my “all engineers think they can do better than their colleagues” observation. How can you tell when when an engineer tells you “the code is a total mess, we need to completely rewrite it.” Since I’m not an engineer, I can’t call fooy very easily. Then again, if I was an engineer, I’d probably believe since I could write it better myself, refactoring must be OK. 😉 This is a tough call!
One argument is that refactoring can be an alternative to upfront design. In this scenario you don’t do any design at all. You just code the first approach that comes into your head, get it working, and then refactor it into shape. …Those who support Extreme Programming often are protrayed as advocating this approach.
Blah! This sounds terrible to me. Say I’m the architect for your new dream house and I tell you, “I’ll have the contractors here tomorrow to start work. We’ll figure out the design as we go along and fix any problems along the way.” What a terrible way to manage a project. You can most certainly take planning too far and never ship anything. But I rarely see this as a problem. I more frequently see software that doesn’t do what is was supposed to do which to me signals a lack of forthought.
My main take away from the refactoring book is that refactoring is about making small incremental changes to code to make it easier to manage. Every change should be testable and introducing new code shouldn’t effect old working code (unless it needs to be restructured to make the new code possible). Sure there are large refactoring projects where you effectively bulldoze everything you have and start over. But it seems the author doesn’t believe this is the usual. Writing code is about constantly making changes to software that makes it better over time. Managing software projects for a while, I don’t get the sense that this is standard operating procedure in most companies I’ve worked at. Projects run from more of a “is it done yet?” mentality – – good code or not. I’ll bet if code were as easy to see as say a user interface for a new application, management would be all over making sure their engineers were focused on writing good code.
In the end, it looks like to me that organizations need to advocate an environment of excellence for software quality. Sure you need to balance time to market, etc. But since quality is usually the first thing thrown out the window in high tech, management should go out of their way to make it clear that expectations are as high at the code level for projects as the external customer facing level.