Many programmers seems to get caught up on the idea of refactoring.
Most of us are familiar with the Boy Scout rule which says:
Always leave code better than when you found it
But do you actually apply it in your day to day work?
I’ve found that for myself the answer to this question is sometimes “no.”
Why we don’t follow the rule
Personally, I know that there are many reasons why I have failed to follow the Boy Scout rule in my own day to day coding activities.
How often do you say to yourself something like:
“Yeah, I’ve just got to get this code checked in. I don’t have time to clean it up.”
“Refactoring this correctly would take too long, and I want to make sure I do it right.”
At first glance, these seem like perfectly valid excuses, but the problem is that the cumulative effect of this kind of thinking is exactly what causes code rot.
“Code rot” is when code from your application begins to become brittle and hard to maintain.
As software developers we should really strive to prevent code rot, and regularly refactoring and cleaning up code, is like brushing the teeth of our application.
There are definitely a large number of excuses I come up with for not refactoring code, but I would say that the number one mental block is this idea of perfection and needing to do it right.
Small refactorings are good!
One thing I try to tell myself is that small refactorings are good and I don’t need to solve the whole problem all at once.
We shouldn’t let the fact that we can’t completely clean up a section of code or refactor it to the final structure we want, prevent us from putting that code on a bus headed that direction.
Many programmers tend to have the perfect solution mindset which requires us to find the 100% best solution to a problem and think that the 95% effective one is no good.
This mindset can be a huge stumbling block to productivity and it can also be a big hindrance to keeping our campsite clean.
It is often helpful to embrace that a series of small changes can be more beneficial than one large change of the same resulting magnitude, even if the small changes end up requiring more total work.
The reason for this is two-fold:
- Big changes rarely actually get done, so they are put off
- Small changes usually are more natural and evolve the code in an organically correct direction.
Going backwards to go forwards
I even find that many times I take one step backwards in order to go two forwards. Refactoring sometimes has to just progress naturally as you make something clearer, only to undue it a bit later with another change that ends up making more sense once you can actually see the problem being solved more clearly.
Think about solving a Rubix Cube. If you have ever attempted to solve one of these things, you know that sometimes you have to wreck that perfect wall of green in order to start getting the white blocks in place. Many times it is impossible to solve a Rubix Cube without traversing backwards in the solution first.
The point is, don’t be afraid to get out there and make something clearer, or go a direction that seems like it will at least improve the code.
You don’t have to find the perfect design pattern to refactor the code into in order to start making changes.
- Start by changing this variable name to be a bit more clear.
- Extract those lines of code into a method that makes that functionality more clear.
- Get rid of some duplication here and there.
The active code reader
When I am in my “zone” and doing things right, I am even refactoring code while I am reading it.
There is no better way to understand some code than to refactor it.
Think about it, how do we learn?
We read something or are taught it and then we rephrase it differently to confirm understanding.
“Let me get this straight, are you saying… blah blah blah?”
“Oh, now I get it, if I do blah and blah then blah blah?”
Why shouldn’t we do this with code?
I know some of you are really scared by this idea, and you're saying “nope, don’t just go touching code you don’t understand, John. You are not getting anywhere near my code base.”
But, give it a shot, what is the worst that is going to happen? You are going to refactor yourself into a dead end and have to revert your changes?
More likely than not, you will end up learning the code better and improving it. Two for one!
One more analogy then I’m done
Ever solved a crossword puzzle?
Did you sit there and immediately fill in all the answers one by one?
Perhaps you filled in some answers that you knew. Perhaps the short ones first, then you went back over all the clues again and suddenly found that with some letters filled in you could better guess the clues.
Most likely you made several sweeps like this until you finally solved the puzzle or gave up in disgust wondering why you wasted an hour of your life and who the heck studies books on geography that could actually solve this puzzle.
Do you think it would be any different with code? Making small refactorings is like filling in the clues you know the answer to in a crossword puzzle. As you keep refactoring, the answers to other puzzles about the code and which way it should go become clearer and clearer.
Don’t try and solve the whole puzzle one by one in a single pass.