It is a truth universally acknowledged that a developer in possession of a codebase must be in want of refactoring time.
Technical debt is built over time – the newer your codebase, and the more quality focused you are, the less you may have, but I still think that you have some. Maybe there are some obsolete interfaces used previously? Maybe what was a good idea 6 months ago just isn’t any more? Maybe the functionality has morphed over the last years and the existing base does not allow easy expansion for the future?
Or maybe there was simply too much time pressure in the past and not enough focus on ensuring that the code was up to standard!
Where I work at the moment we have a lot of technical debt. With over five years of waterfall development where delivery time was pushed over quality, and the time spent starting Scrum and trying to change this mind-set, have not been kind. But we are improving! And of course, knowing you have a problem is part of the solution, burying your head in the sand never solved anything!
I have never seen a company where technical debt is not a difficult subject between developers and stakeholders. The conflict between trying to get new features and making sure that things are maintainable and scalable are always hard to balance. The question is just how do you fight the technical debt whilst still providing business value during your sprints. If you are a developer and you find bad code then you want to fix it – but at what cost?
Where to Start
Before you start you have to ensure that you are providing value to the business whilst you are cleaning the codebase. Simply spending all your time refactoring to clean up the code will lead to two things:
- Zero value for the product owner: Cool! The code is clean and looks great, but it had been running without a problem for a number of years now, and we were not planning on changing it any time soon so where is the current value?
- New technical debt: with the time needed to clean the whole codebase you will still have old code when you are done. Just new old code.
A colleague who proof read this for me when I first wrote it came up with a couple of questions he asks himself before refactoring. This is the one that I think people maybe do not ask themselves enough:
- Which changes are needed to make the implementation of the user story quick and successful?
In order to try and make sure that you can clean code whilst providing value there are three stages of refactoring that I see (feel free to correct me in the comments if you see it differently ;p).
Quickly Refactor the code
Firstly, if you are working on code and it needs minor refactoring (let’s say 20% of the story time) then just do it and make the code a nicer place. I would like to hope that all developers feel that they have the mandate for doing this!
Serious Refactoring of the Current Code
Secondly, if your code is going to touch old code and make it worse due to the (poor) existing structure then it needs changing full stop. This is included in the points assigned to the story and when the product owner asks why some simple stories are so complex you can explain.
At this point they can decide what the ROI is on the story – is it really worth investing all of the time on making it correctly, or should the story be delayed until stories with a greater ROI are complete. One thing we try not to do here is make the existing poor code really poor by hacking away!
Of course there can also be the times when you need to work on some terrible code, but not in a way that makes it any worse. If all you are doing is adding a few extra lines of code without affecting the complexity or maintainability then I feel you should be asking yourself if the refactoring is really needed at that time.
Time for a rewrite!
Thirdly, when it’s known that a project is going to need some serious refactoring before we start, ask for explicit stories to do it. A couple of examples of this where I work were related to web services used for a couple of product groups that we have. These had been quickly changed again and again in waterfall projects and never cleaned up (the time to clean up that was promised never quite materialised! Sound familiar?). Duplicate, dead and unused code was spread like spaghetti and adding anything new was both dangerous (you never knew what was going to break) and time consuming trying to pick apart the paths through the code. Here we offered two options to the product owner. Give us a story (or multiple stories) to rewrite the service from the ground up to support the functionality you want and need, or simply accept the limitations of the service and leave out some of your front end functionality.
One time the product owner decided that the whole functionality was really important and we had the stories to write the functionality that was needed. Another time it was decided that the ROI was not there for the extra work and the scope was reduced to only use existing functions in the web service.
Using these options I would hope that the transparency is there to allow the product owner to make informed decisions about the work that the team does, and that value can be given to the business and at the same time the codebase can be cleaned up and improved. Communication is key in making this work, as is building trust – starting refactoring projects without telling the Product Owner and having stories carried from sprint to sprint does nothing to make the teamwork easier!