Refactor or Die

The following article is the follow up to my last article about never refactoring (Don’t Let Your Developers Refactor). It is intended for developers as a resource for understanding the why, when, and where of refactoring.

Refactoring is an inevitable part of software development. It is necessary when new features are added, requirements change, or even naturally over time (software entropy). If we as developers don’t refactor our code we will quickly incur a lot of technical debt. But at the same time, convincing a manager to allocate time for refactoring is challenging unless they have been a developer themselves. Remember that refactoring has no benefit the manager or the customer can see.

Refactoring vs. Optimizing

A lot of times the terms refactoring and optimizing are used synonymously to mean, “improve code.” I prefer to consider them not only different terms but even opposites for the most part. One similarity they do share, however, is that after refactoring or optimizing the behavior of the code doesn’t change.

Refactoring code is the process of making it more human-readable, extensible, and reusable. Optimizing code is strictly for improving the performance of code or in other words making it more machine-readable.

Here is an example of refactoring:

// Before: Ambiguous code. What's going on here?
function getTemp(device) {
    const temp = device.getTemp();
    return (temp - 32) * 5 / 9;
}

This code is a little ambiguous. If you’re unfamiliar with that formula you probably have no idea what is happening here. The following code snippet has been refactored so it is much easier to understand what it’s doing.

// After: Human-readable code.
function getTemperatureInFahrenheit(device) {
    const temperatureInCelsius = getTemperatureInCelsius(device);
    return convertCelsiusToFahrenheit(temperatureInCelsius);
}

function getTemperatureInCelsius(device) {
    return device.getTemp();
}

function convertCelsiusToFahrenheit(temperatureInCelsius) {
    return (temperatureInCelsius - 32) * 5 / 9;
}

There are some interesting things you might notice. First, I wrapped the object method getTemp in the function getTemperatureInCelsius. This is assuming I don’t have control over renaming the method getTemp. Second, all of the function and variable names are significantly longer. They are much more descriptive now. Modern IDEs come with autocomplete so there shouldn’t be an increase in development time.

From this refactoring example you can see how the code would actually be slower since it includes additional function calls. As developers, our time is more important.

When to Optimize?

Never.

When to Optimize, Really?

There are two conditions that must be met before you can optimize your code. One, the program has to be noticeably slow. Two, you must have an actual measurement or profile of the software to know where to optimize instead of guessing.

When to Refactor?

Refactoring is an ongoing process that must become a part of your daily routine. It shouldn’t be something you wait to do until your technical debt is so bad that refactoring is unavoidable. Waiting until it’s unavoidable would be like waiting to pay your mortgage until you get a foreclosure notice.

Another important thing to remember about refactoring immediately is the Broken Window Theory. It states: Consider a building with a few broken windows. If the windows are not repaired, the tendency is for vandals to break a few more windows. Eventually, they may even break into the building, and if it’s unoccupied, perhaps become squatters or light fires inside.

The same is true for software development. If a few pieces of bad code are allowed then a few more will show up. Eventually the whole system will be “buggy” and that will just become the company culture.

What to Refactor?

A code smell is a surface indication that usually corresponds to a deeper problem in the system — Martin Fowler

It can be challenging to know exactly what to refactor but experience and intuition can go a long way. Look for Code Smells. Wikipedia lists several that are pretty good indicators. I would like to list a few that I’ve seen frequently in my career:

  • Duplicated code: identical or very similar code exists in more than one location.
  • Large class: a class that has grown too large. See God object.
  • Too many parameters: a long list of parameters is hard to read, and makes calling and testing the function complicated. It may indicate that the purpose of the function is ill-conceived and that the code should be refactored so responsibility is assigned in a more clean-cut way.

How to Convince Managers to Allocate Time to Refactor?

If you’ve been following along then you should realize what my answer is going to be: you don’t! Instead of convincing managers to allocate time to refactor you need to include the necessary refactoring time when specifying time for features. It’s kind of like the adage about eating out and tipping waiters/waitresses. If you can’t afford the tip, you can’t afford to eat out.

Conclusion

Great developers make it a habit to refactor as they go and don’t leave any broken windows. If you’d like to read more about refactoring Martin Fowler’s book Refactoring: Improving the Design of Existing Code is a great place to go from here. If you are looking to improve yourself as a developer I also highly recommend The Pragmatic Programmer: From Journeyman to Master.

Have you found other tricks to help you refactor? I’d love to hear them in the comments!

Bookmark(0)

No account yet? Register

Published by Chris London

A serial entrepreneur, Chris is currently co-founder and CTO of tech start-up Cinch. Cinch is an automated marketing platform designed to share the right message at the right time with your customers.

Leave a comment

Your email address will not be published. Required fields are marked *