The Boy Scout Principle
Last time we looked at refactoring. How real refactoring isn't re-writing big chunks of legacy code, it's cleaning as you go. Making sure the code you write now is clean. But what do you do about those big lumps of legacy? They weren't written with "clean" in mind, they were written with "hack it together to meet the date" in mind instead. It's messy and it's slowing you down. What do we do about it?
Well, we need to refactor it. But how, if we can't spend the whole sprint rewriting a big chunk of it? We need to stop thinking big - think small instead. Use the Boy Scout Principle - leave the camp ground cleaner than when you found it. When scouts leave a camp ground, they spend a few minutes cleaning up. Not just their rubbish but anything else they can find left by previous campers. And crucially, they don't try to clean up the whole forest, or even the whole camp-site - that would take weeks - they just clean up the area they were using.
By using the boy scout principle, we can keep refactoring of legacy code down to small, manageable, clean-as-you-go chunks. Whenever you have to touch legacy code, you have a decision to make - is this so badly broken that I can't proceed? If it is, then the boy scout principle probably won't help you. Sometimes it's just so messy that only a re-write will do. But we should have a fair idea of the areas of the code that are in that state so we can plan for this (if not, maybe an exploratory spike to learn where they are might be in order). We know we will need to touch that mess when we implement feature X, so let's plan in a re-write before then. Re-writing code isn't a problem if it's planned. It's unplanned rewrites that cause chaos.
But if the code isn't that bad, if it's messy but not bad enough to stop you entirely, then let's apply the boy scout principle. Let's clean up the camp ground. Write your new code, get it working, make sure the tests are green (you are writing tests aren't you? If not, you are writing brand new legacy code). That new code is our camp ground. Not the whole module, just our new code and the area immediately around it. Extend your test coverage to the lines above and below your new code. Extend it to the function that called your new code and maybe to some key functions that your new code calls. Then refactor.
This should only take you a short time. Around an hour is good. That's the trick. It's easy to get carried away and refactor all day but you need to be disciplined. Set aside some cleanup time. Timebox it. Decide where you get your biggest impact for the time spent and focus there. Set a timebox, decide where to spend the time, refactor then stop.
Make sure that your refactoring is covered by tests. Write the tests first. I don't care what you think of TDD normally; in this case it is essential. You need to refactor without changing behaviour. The only way you can do that is by having tests that confirm the existing behaviour before you start fiddling with the code. Otherwise you will break things and spend the rest of the sprint fixing the mess you made.
Yes, you will be left with messy code. But crucially, it's cleaner than it was before. Remember, the boy scout principle isn't "leave the camp ground spotless", it's "leave it cleaner than it was before". If there is still mess, clean it up the next time you touch the code. Or, if it's really messy, do what the scouts do and plan a clean up trip later. Remember, rewrites aren't bad, if they are planned.
"But", I hear you saying, "isn't this still unplanned work? Aren't we still taking extra time, that wasn't planned, to do that cleanup?" Well, yes, we are. That hour you spend cleaning up is an hour you can't spend doing something else. So let's plan for it. How? By including it in our estimates.
Whenever we estimate a story, ask yourself whether this will touch legacy code. If it will, include some clean up effort in your estimate. Maybe any story that touches legacy needs to be bumped up to the next bucket. So a 2 point story that touches legacy becomes a 3. A 5 pointer that touches legacy becomes an 8 and so on. That makes intuitive sense because the larger the story, the larger the footprint (usually) and so the larger the area that needs to be cleaned. But whatever works for you.
So, we can turn our big messy, unplanned cleanup into a short, planned, timeboxed activity by clearing the boy scout way - by always leaving things cleaner than when we found them.