Nothing kills the productivity of a development team more than working on and supporting poor quality legacy code.
You start work in a new team, full of grand ideas and determined to do things the right way. Then you discover the morass of existing software that is sitting at the heart of the system. This code has been around for years. Nobody likes it, everyone wants to get rid of it. But that would mean spending lots of time and resource and producing little, if any, business value.
So what is the best way to tackle legacy software?
There are a number of options.
You can leave the legacy software alone and hope it gets better with time, as each change and bug fix is applied. Sadly, this rarely works. Why? Because nobody wants to work on this code, it saps the developers' motivation and blunts their professionalism. It is so time consuming to modify the legacy code and as a result developers natural instinct is to rush the job and cut corners.
How about building a like-for-like nextgen system and replacing all that rubbish code? Sounds great in principle, but in practise this is a dangerous approach. Legacy code often lacks decent functional documentation. How can you replace something if you don't know what it does? Also, the nextgen project will be under pressure from day one. You aren't delivering any new business functionality so the only way to justify the time and expense is to finish the project. Finally, once nextgen is ready, there is the challenge of switching over systems, migrating data and re-training.
You could build a nextgen system that doesn't just replace the old system, but includes some additional functionality. At least with this approach the business is more on side. But you have set yourself a really difficult task. Not only are you replacing the heart of your existing software, but you are also developing a functionally more complicated solution. Add to that the switch-over becomes even more difficult to achieve. In my experience this implies a large and complicated project that has a high risk of overruns or even outright failure.
How about replacing your legacy code with an off-the-shelf system? This is such a tempting solution. It is often appealing to managers who can easily sell this approach to the organisation executive. An important question to ask is does the off-the-shelf replacement exactly match the functionality of the legacy system you want to replace? If not, then how will it integrate in to the other code you use? What about monitoring, support procedures and training manuals that need to be re-written? It is often to the advantage of the software vendor selling you the replacement system to underplay any potential integration issues.
What is an agile approach to this problem? Agile encourages flexibility and frequent releases rather than monolithic projects.
An agile approach to legacy code could be to divide-and-conquer.
Look to:
- break the old code up in to components each with a discrete API
- separate out the database schema so that it matches the components
- divorce the UI from the business logic
Ideally you make these changes as early and as quickly as is possible, while still maintaining delivery of new business functionality. As you are retaining much of the legacy code and the system behaves in the same way, the overhead of the work should be tolerable. You don't need to change your documentation or retrain your users or rewrite your system monitoring.
Once you have a componentised system, you can then start to replace the components in a prioritised fashion. There will still be risk, but you are no longer putting all your eggs in the one basket. If things go badly, you still have a working system in place.
I wondered for a long time about why this approach isn't used more often than it is. What I have realised is that this approach is simply not very glamorous. Selling it to an executive is difficult and it will never sounds as appealing as the nextgen or off-the-shelf approaches.