Refactoring: break your code fast, fix it faster
About a year ago, I wrote a really short post about failing fast not meaning that we should not think first. Now that I think about it, I don’t believe I was fully in the right. The saying about failing fast was never about not thinking too long. It seems to be about experimenting with what you have in mind. We all have great ideas 24/7, cool software designs, new paradigms to try and so on. The point is to try to make things work in your first try, and the next one and so on. Which makes me think about refactoring.
You have a piece of software covered by tests and you want to change it. If you edit a tiny bit and that your tests still pass you’re good to move forward. Bit by bit you can improve your bit of software. And the fail fast is more about when your tests go all red. Because you made so little changes it is easy to correct and adjust them. As a result, you can move faster over time. Alistair Cockburn says it better than I can: « With design
The chance we have with software development is that we get relatively instant feedback about our changes whether it is through unit tests, continuous integration or even (heavens forbid) angry user reviews on an App Store. We need to take that chance to deliver innovative solutions before they become rotten.
The problem nowadays is that negative user feedback hurts business reputations and comes faster than code changes. Sometimes that feedback comes from a bug that got fixed in a place but that was a duplicated bit of code. Duplication that spreads across the system, makes it slower to add new features. Fewer features mean fewer chances to be ahead of the game and deliver an innovative product.
The Big Refactoring, between deceit and gamble
For the longest time, I heard about The Big Refactoring. You know, the promised day where we would stop everything and fix a system that became a patchwork of code. It is not a bad thing to want it to happen, it proves a will and an acknowledgement of need for improvement. However, every single time I heard about it there was something more important coming up. A new feature, a deadline, another team requiring help. Every, single, time.
For the longest time, I thought that refactoring was that unreachable developer dream that would end a nightmare because we would have to rebuild the design of the software. I thought we had to stop any development so that we would rebuild everything. This is actually a very risky approach as sometimes it is understood as breaking everything for a few days, weeks or even months. Breaking everything with no way to validate changes made during that time is dangerous. Yet I thought that was the only way out of rotten code. Now that I think about it, it is the equivalent of chopping your arm off to get a new one. It may work but you can’t be sure until your done linking the new one.
How we should tackle refactoring
Over the past year or so, I have been trying to change portions of code I’d work on bit by bit while making sure tests still pass. Why do I write about it now? Because I started reading “Refactoring: Improving the Design of Existing Code” by Kent Beck. Turns out without knowing it I was actually practising what “real” refactoring is. The fun thing is that you actually can move faster. Remove a bit of duplication here, green tests, keep moving. Unclear bit of code, rewrite it, green tests, keep moving. I have been able to write software much faster while writing clearer, cleaner code. Code that will be easier to maintain and improve. As a result, I can develop more features with fewer bugs faster.
If your code is cleaner and clearer you will have fewer bugs. Why so? Because if your code intent is clear then it becomes easier to spot mistakes as they would not fit the intent. Then again, the intent needs to be clear from the get-go. It has to be a given that if you don’t know what you want your code to do, you cannot expect a machine to. I am starting to feel like I am repeating a lot of obvious things so it is time to wrap up this post.
Yes, you should refactor your code as much as you can. You should always be able to validate your refactoring for each change you put in. No, you do not have to refactor a whole solution at once, you would want to refactor a localised portion of code. Ideally, refactor when you need to modify software before adding a new feature or to improve the clarity of existing code.
Going further with books
If you need help with refactoring and do not know where to start I would say that it would not hurt you to have a look at design patterns. GOF got a thing or two for you to learn. You can also read “Clean Code” from Uncle Bob. These should give you a good start to spot bits you can refactor in your code in an effective manner. Long story short, the more you will be reading the better will be your refactorings.