If it ain’t broke don’t fix it or fix it before it breaks?
Stop me if you’ve heard this one before. Somewhere in organization X there is this piece of legacy code that is quite business critical. It is very old and probably complex. Problem is that it’s so old that nobody really knows how to maintain it. It’s probably written in some language someone decided it wasn’t interesting to invest in anymore. So it just sits there. It works, it’s important but nobody dares to touch it because if it breaks nobody knows how to fix it.
You’d be surprised how often this type of scenario happens. Some mysterious logic that’s been in use forever, is quite important but nobody knows what it does. I’ve seen cases where a very expensive MainFrame system is kept around just to be able to house this mysterious black box code. As the saying goes, if it ain’t broke don’t fix it, but depending on the criticality of that piece of code the risks can be quite substantial. And even if the risks seem acceptable leaving any code running that you can’t maintain is never a good idea.
With all the interest in µservices of late I figured that it was a good time to take this topic and try to formulate a basic approach to address this problem using a service. What I want to do is go through an approach that will allow you to isolate the problem and allow for it to be replaced in a way that should not disrupt business and allow for a reliable way to replace this code.
The core concept is simple. Turn the black box code into a autonomous (µ)service so that you can replace it with another service. Given the core problem (“don’t touch the code!”) this might sound tricky but it shouldn’t have to be. The below diagram is representation of how things might currently work:
Basically this is a monolith. A single binary where components communicate locally to each other and to our mysterious code. Now the idea is to change those local calls into remote calls so that we can isolate our mystery code. To do this we wrap our mystery code with a remote API that accepts remote calls and translates them into the local calls to the mystery code.
Here I’m not taking performance into consideration. If that is a factor the wrapper might need to expanded into a proper µservice that better fulfills the business capability the mystery code is a part of.
This wrapper can then move into it’s own service outside of the application or (like in the case of the mainframe) other parts of the application can move elsewhere. Leaving the mystery code as a service.
I wouldn’t directly classify this service as a µservice. But it should satisfy some important criteria like being autonomous. Main reason to hold back is the extent to which this service would be able to provide a business capability. That being said the approach should fit nicely in a µservice architecture but will more likely be part of an µservice instead of being one all by itself.
If nothing else this approach should allow you to break these kind of application components off into an autonomous service. Thus allowing for more flexibility in it’s actual implementation, to ultimately result in something that is maintainable. Preferably before it breaks.