Working with Broken Windows
I recently stumbled upon an article by Martin Fowler on opportunistic refactoring (http://martinfowler.com/bliki/OpportunisticRefactoring.html). this reminded me of something discussed in the book The Pragmatic Programmer — The Broken Windows Theory. This theory originated from studies showing that neighbourhoods that have buildings with broken windows, graffiti on the walls etc. are more likely to have criminal activity. Then the same theory is applied to programming — if you work with bad code inherited from someone else it is more likely to introduce more bad practices yourself. And you will be thinking — “It’s all bad anyway why bother”.
Now both the article and the book suggest that while adding new code you can refactor existing bad practices. This is all nice and true but what happens when you need to refactor things on a bigger scale? Or if you are supposed to work on a small task that shouldn’t take long — should you spend 5 hours fixing something else? In that kind of environment statements like the following start to make sense to people due to the complexity of the problems.
So how do you deal with technical debt without spending months rewriting the whole system? Here are the things I’ve found useful
Keep track of it
Everyone keeps a bug database — so why not do the same for technical debt? You would get the same benefits — you know what’s going on in your system, you can prioritise what to fix next, you can refactor before writing new code.
What you also get is history — every team has been in a situation where no one knows why a class is written the way it is because the guy who wrote it left 2 years ago. If you actively keep a record of things that should be refactored you can add a description on why something was done in a certain way before everyone forgets.
Build a strategy
Sometimes technical debt is introduced as a result of people not talking to each other before writing code. The same can happen when refactoring. It is important to come up with a plan as a team for how to tackle a big piece of code that needs fixing. This can prevent awkward situations where more technical debt is introduced while trying to reduce existing one.
Set time aside
It’s very hard to sell the idea of spending 6 months rewriting the entire codebase to the business. But it’s relatively easy to set aside a week in which the whole team can refactor a component that has been causing problems for months. Or you can have 1 developer working on refactoring while others are adding new features.
I was in a situation once where in order to meet a deadline we had to release an iOS app with some parts of the code not meeting to usual quality we strive to maintain. After the release we spend one week getting rid of all the identified technical debt. In result the app became faster and easier to add new features to.
Divide and conquer
Refactoring a big chunk of code can be off-putting as you know it will take more time to do then you've got. What you can do in situations like this is just introduce a way of fixing all the problems but leave some of the code as is. Then when someone else uses this code later on they can follow the example and refactor another bit. Or when a new developer joins the team they can be assigned to finish the refactoring. Thus getting introduced to the codebase as well as making an actual contribution.
In a team I used to work in, one of the components of our application was very hard to test due to the way it was designed. As there were a lot of classes that needed refactoring this problem existed for a long time. Finally we refactored just a couple of the classes that we wanted to test the most. After that, anyone could just follow the example and refactor any of the other classes when they needed to.
Refactoring things on the spot is a very good thing which is keeping the quality of the codebase but can be very frustrating at times when scale and complexity is preventing you from fixing a problem time and time again. For those situations it’s good to have an alternative other than “Let’s just start from scratch and build it right this time”.