Refactoring has a price. Not refactoring has a cost. Either way, you pay.
I recently heard this phrase:
Good habits have a price. Bad habits have a cost. Either way, you pay.
That is a great life lesson. But it’s also a great lesson for our team and codebase.
Refactoring is a good habit.
I’m talking about refactoring as test-driven development (TDD) defines it – something you do with every test and feature. I’m not talking about pausing feature work for a month so we can do refactoring.
In TDD, we refactor as the third step of the red-green-refactor cycle:
- Red: write a test that fails
- Green: get the test to pass
- Refactor: clean up the changes. Improve design.
Many developers think our work is done when the code “works” (when we get to green). After all, the tests pass. So, we’re good, right?
I think that misses an amazing opportunity to improve our codebase!
The work is not done when the code works. The work is done when the code works and when we’ve made sure the changes are designed well. And to do that, we need to refactor.
Of course, refactoring after every feature has a price – just like good habits. It takes time and discipline. But people erroneously think that the alternative is free – that not refactoring has no cost.
Yet, if we don’t refactor continuously, we eventually have to pay the cost.
That cost is likely imperceptible at first. So, we carry on without refactoring. Our codebase atrophies day by day, feature by feature, every change seemingly not affecting the whole.
But one day all the cruft calcifies, and the numerous incompatible changes and features grind our progress to a halt. It is suddenly impossible to add new features without breaking something else. Bugs come up faster than we can squash them. And every feature takes longer and longer to ship as we have to verify that nothing is breaking.
The cost of our bad habit accumulates until we cannot foot the bill. That’s when we throw in the towel, declare code bankruptcy, and call for the “great rewrite”.
We either refactor continuously as we build features – paying the price. Or we slowly accumulate cruft until our codebase is impossible to change – paying the cost.
Either way, you pay.