Evolving a Software Architecture with Three Buckets
Evolving a legacy software architecture can be a challenging exercise, figuring out where to start is often the hardest part so we need an approach to get the ball rolling. It could be a codebase which you have worked with for years our it could be a codebase which you have never worked with before, such as when you start a new job.
The motivations behind evolving a legacy software architecture can vary but it is always about increasing the value of the software in some way. For example, you might want to enhance the reliability, maintainability, flexibility and horizontal scalability of a monolithic system, this might involve slicing it vertically into separate independent services. The consensus might even be more drastic, the team may have concluded that the current system is unmaintainable and that it must be completely redeveloped.
Of course we must not rush into anything, we need to analyse the codebase in depth and construct a pragmatic plan to bring the architecture into the future, existing systems usually contain a lot of hidden value and intellectual property which must be uncovered.
First of all you need to fully understand the whole system, reading any existing documentation is a good way to start but that only gets you so far. When analysing code you should draw sketches to support your mental model, usually component diagrams and maybe some sequence diagrams depicting how the components interact with each other. Once you have a good understanding of what is going on you can start to classify the components into three separate buckets.
The Keep Bucket
This is obviously for any components which are good, well structured, have adequate unit test coverage, meet existing requirements, in other words, these are the parts of the system that people don't moan about! It can also include some uglier code so long as it is easy to understand and doesn't scare anyone too much.
The Tweak Bucket
This is for anything which is reasonably good, the code might need to be restructured, could do with some more exception handling, some more tests, general tweaking so that it resembles the code in the Keep bucket.
The Scrap Bucket
Hopefully this is a small bucket, and if you aren't too critical it generally is. This could be the remains of a previous employee who has long since scarpered to make life hell for some other poor soul or maybe it's just old code which hasn't been touched in a while and no longer meets requirements.
With the components categorised, you are now in a place where you can start to formulate a plan. You can size the refactoring work required to get the Tweak bucket up to standard. You can then focus on redesigning the components in the Scrap bucket and size the redevelopment effort. Obviously you need to ensure that you cater for all of the existing requirements, such as those subtle undocumented nuances which were patched over a gloomy weekend sometime in the past.
The three buckets approach is a simple but effective way to get your head around what needs to be done to start evolving a legacy architecture. It's an iterative process, the components which fall into each bucket will change over time but this approach will get you started on the right path.