I've read through most of Fowler's Refactoring book and have refactored many applications in my past big and small.

One of the harder things I find to teach is "when" to refactor. I tend to do this based on a gut feel which has served me remarkably well in the past. However, when getting into discussions with people about whether a piece of code should be left alone or refactored right now it is hard to stand by the "gut check".

I feel like there should be more rigorous approaches to this, but am not sure what they are.

I understand "code-smells", red-green-refactor and other thoughts, but often I feel that the best time to refactor is not the first time you write the code, but the second or third time you are using the code and realize that it is actually a problem and is in actual use.

9 Answers
9

Refactor when the cost of refactoring is less than the cost of not refactoring.

Measure "cost" however you can. For example, is the code so poorly implemented that trivial bugs cost hours or days to fix? Will refactoring allow you to gain more customers, or increase capacity, or improve performance and thus make your existing customers happier?

In other words: "it's worth to refactor when it's worth to refactor". Duh. Well, it's not really an answer, is it :) Measure "cost" however you can. - OK, how? Isn't that the gist of the question? What time perspective should be applied when measuring that cost?
–
Konrad MorawskiFeb 20 '12 at 15:52

1

@Morawski: no, That is an incorrect paraphrase. I said it's worth it to refactor if the value received from the refactoring is greater than the cost of the refactoring. That's not the same as saying "it's worth it to refactor when it's worth it to refactor". Calculate the cost of refactoring. Calculate the cost of not refactoring. Which is bigger?
–
Bryan OakleyFeb 20 '12 at 16:47

@BryanOakley : problem is, you can't "calculate" these costs. You can at best estimate them, which is really hard to do when it comes to the cost of not refactoring. What maintenance cost multiplicator do you apply to the unrefactored version vs refactored version ? How do you know if the code in question will have to be maintained or changed at all ? How do you estimate the number of bugs it will generate ? In the end I guess we all unconsciously make these kind of estimations as part of our decision process when we think about refactoring, but there's no accuracy to be expected from it.
–
guillaume31Feb 24 '12 at 16:50

1

@ian31: true, you can't calculate values, and the best you can do is estimate. Still, this is the only really valid way to decide whether to refactor or not, assuming you have limited time and resources. You need to decide whether the refactor is worth it. How you define "worth" is a very inexact science. The point is, you shouldn't refactor on a gut feeling -- there should be a good reason for doing the refactoring other than "I want the code to be prettier".
–
Bryan OakleyFeb 24 '12 at 18:19

When your gut is telling you that you should probably do some refactoring, It's likely it's your instincts telling you a little late that you've been putting something important off for too long.

I understand "code-smells", red-green-refactor and other thoughts, but often I feel that the best time to refactor is not the first time you write the code, but the second or third time you are using the code and realize that it is actually a problem and is in actual use.

There are effectively two levels to refactoring. The first is the obvious issues that appear when you first code. These are the little optimizations that cost you very little to do up front. Things like keeping your methods and classes small, and adhering to DRY and SRP. Then you have the additional stage of dealing with major flaws in your design, which may not be immediately apparent until your code has a couple of miles under it. It's this second level that you are talking about, and yet in order to ensure that later refactoring isn't too costly, you need to have already written your code in such a way that the effort you later envisage is made easier and less costly, which means doing an early refactoring.

As Jeff mentioned in his answer, "time is money", particularly in companies where the workload is high and the risks even higher. Time spent up front making sure the code is in its best possible state is time saved later, when teasing out what should have been an easy refactoring turns out to be a major operation.

When writing software, every moment spent improving your code up front is time saved later, when you're really going to need it. The earlier you refactor, the clearer your later changes will be. It's like making a down payment in today's dollars against future technical debt which will be in tomorrows inflated dollars.

In any case, refactoring shouldn't be a task that you put off until some mysterious future when the software is already complete and stable, as it increases your risks later when the stakes are much higher and the product much more difficult to change. Refactoring should be a part of your daily activities, and this is the essence of the Red-Green-Refactor philosophy that you mentioned.

I think your question can be answered differently by each developer and even the management in charge of the programming.

My personal preference is, whenever I learn something new, or improve my best practices, I refactor the code that I can - I like to keep my code up to standard as soon as I learn what the best standard to use for that situation was. I am allowed to do this though because it is a smaller company that uses the same software for long periods of time.

In a bigger software development company where time is money, it may be to just start designing with the better practices you learned from this point forward, do not worry about refactoring until verison 2 of that specific software?

I feel teaching when to refactor really depends on the company you are currently in.

I feel like this just says "You should refactor" without answering the harder part: "I feel like there should be more rigorous approaches to this, but am not sure what they are."
–
HortitudeFeb 23 '12 at 18:58

I don't know what to say except feel what's painful to maintain, sniff for code smells and use your experience. I doubt there will ever be a definitive, established method that tells you when and what to refactor if that's what you're looking for.
–
guillaume31Feb 24 '12 at 16:25

When I was first learning about refactoring, my mentor told me: "Do it twice, hold your nose. Do it three times. refactor." (Thanks, Josh!) To be specific, what he was saying was that when you are about to write the same block of code for the third time (or even a similar code pattern), that is the time to refactor. I have followed that for the past 10 years, and found it to be a sound enough rule of thumb.

Using Eclipse, or similar IDE which has strong refactoring support, reduces the effort to do the refactoring. The IDE support makes it more likely you will refactor as soon as you hit the "third time" (or see the need), instead of seeing it as additional effort.

Also - TDD is a big help here too, since you can keep running your tests as your refactor, and know that you haven't broken anything.

Refactoring by its definition is a process. This implies that you should not strive to find spare time to do the rafactoring task, instead you should keep refactoring all the time when you come across code code that could be written better.

Personally I like writing evolutionary prototypes, saying it more simply: code that just works, and then refactoring those until they will meet expected coding standards. Another good example is adding additional functionality and refactoring existing code to enable its reuse.

I think, that depends on the demands of the project owner and the guy that answers for the quality of the code. You simply can't decide it alone, when the money of somebody else are under question. It is not a merely professional question, it is more of organizational question, IMHO.

In my 20 years of programming, here is the only rule of thumb that I've actually seen work, which people can stick to, and managers allow time for. (Refactoring is like dieting: sure, "calories in / calories out" is the formula to losing weight, but that doesn't translate into a diet that people will comply with.) And so:

Refactor continuously, as you work. Use Test Driven Development so that you have several red-green-refactor cycles through the day. Refactor just the parts of the code that you've touched.