Sunday, May 6, 2012

When and why should you refactor code?

One of the tenets of the agile methodology is the concept of "re-factoring", or the "disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior".  I consider an attitude that favors re-factoring to be a very important trait of a good software engineer, and vital to the maintenance of quality software.  But, not always.

The "Engineering Tax"

In my team, we call re-factoring the "engineering tax".  That is, we won't always offer up all of our coding bandwidth strictly for the quickest route to the release of new features.  Sometimes we have to take a step back and restructure things for the longer term.  As engineers, we know the code best and it's up to us to recognize these needs when they arise.  We have to tell product managers that it will take longer this way, which means we better have a good pitch as to why it's necessary.

It can be a hard sell, because product managers want features that generate revenue.   If you're spending time on something whose value is not user-facing, they probably don't care about it.   Some of the arguments I make to sell an extended development cycle due to re-factoring are as follows:
  • If we change the underlying data-structures, it will enable a simpler UI.  Simpler is always better.
  • When you want "the next feature" in this area of the product, we'll be able to build it faster.  In fact, we've already thought about the "next feature" you've been considering, and we've realized that this restructuring enables it.  So time now has a direct payback against time later.
  • Our QA for this feature will be shorter, because with less complex code that more closely resembles the business logic, we will make fewer mistakes and there will be fewer bugs.
  • If we're being asked to build something that is "like something else we have, but a little different," we need to combine the code for the two features and share it between them.  This will prevent two parallel implementations going forward, and cut down long-term regression risks.
  • We can build unit tests for the new code, where there may not have been any for the old code.  More QA savings and regression risk reductions.
  • Perhaps our re-factoring plan includes a performance improvement...wouldn't that be nice?
In short, you're trying to sell a lower overall long-term cost due to re-factoring.  It will be difficult to prove ahead of time, especially to a product manager without an engineering background, but hopefully over time you'll be able to look back on some success stories from re-factoring and some failures from when it wasn't done.

When NOT to re-factor?

But like anything, the attitude for re-factoring can be taken too far.  There are right times and wrong times...right reasons and wrong reasons.  Here are some thoughts on when you should re-consider whether a re-factoring project is a good idea, at least right now.

Have you taken the time to thoroughly understand the existing design?
Some engineers have a default attitude that if it's existing code written by someone else, it's therefore bad code and needs to be re-written.  Often times, they're really just facing style differences.  There's more than one way to write good code and you owe it to your forbears to understand their intentions before you throw their code out the window.  In fact, if you decide to do this new thing in a different way, you could be harming overall code quality by introducing yet another "style" into the code and thereby confusing developers that come after you.  The worst travesty on earth is an "improvement" that makes things worse!

What are the product stresses at the moment?
Even as an engineer with a strong re-factoring ethic, you need to respect the point of view of product management.  They may be facing a revenue-impacting deadline that is just around the corner.  They may have made promises to customers.  If you know you can deliver the feature without the engineering tax, and your product manager is making a strong case for it, you need to listen.  You need to consider time pressures in your decision.

Is the re-factoring huge?
If you're wanting to charge an engineering tax of, say, 50%, meaning that half of your coding time is going towards re-writing with no end-user value, then it might not be worth it.  You better be taking a long hard look at the long-term benefits and making every attempt to quantify them so you can justify the cost.  In general, the higher the tax, the more justification is needed.  In my product, we've done a lot of re-factoring over the years, but we've also left a ton of ideas un-done, because the costs simply weren't warranted.

Is it close to a release?
Re-factoring can introduce risk in a code base.  It's more "new" code, and therefore it's more "untested" code.  If you're coming close to a release, you can't afford to introduce such risks, and you should consider making your changes in a code branch with a longer horizon before it ships.

Are you just being a perfectionist?
I've seen some developers who take the attitude to the extreme.   They re-write code they wrote yesterday, or next month they re-write thousands of lines they wrote last month.  I appreciate their high standards in their work, and as an engineer I can definitely relate to the nagging feeling that "I can still make this better".   But this has to have its limits.  Code needs to ship or it is useless to the world.  You need to reach a point where your new ideas go on the engineering backlog and you focus instead of stabilization and shipping.

In summary, the decision to re-factor or re-write code is a subjective one.  It can be difficult to quantify the costs and benefits, and many different engineers will have different opinions.  The factors above are some things to consider.

In my current case, I work on a very old application (10 years), and I consider re-factoring to be critical to its long-term health and code quality, so I generally support and encourage developers to re-factor.  But I also keep them in check with the questions and considerations above, and my vote is not always "yes" to the engineering tax.