In my last post I talked about how to change your release approach by using trunk. The benefit of such way of working is that you can release new functionality much quicker and in smaller batches. However, taking full advantage of such approach implies your applications are modular and consist of blocks of functionality that can be committed and tested one at the time. Most of our enterprise applications are monolithic in nature and as such do not lend themselves to a trunk based approach. So, the question is how to modify them so we gain the level of flexibility required to quickly respond to the demand of the business.
Why not strangulate your applications?
To enable trunk based developments we need to renew the architectural basis of our existing application. Fundamentally we have two ways we can do that, either build a new version of the application and swap one for the other, or change the structure on the fly. The latter is what is called the “Strangler Application” Approach. It reduces the risks associated with transforming applications and allows to continue developing new functionality in parallel with the transformation itself.
So, how does this approach works? What needs to be done?
1. Build an abstraction layer
The first thing you need to do is build an abstraction layer. You expose a number of APIs through which you access the functionality available within the monolith application. Choose the type of APIs you expose carefully as they are the APIs you will continue to expose when your application is transformed. Use a web services approach. These APIs become the way to invoke the functionality available in your application digitally. Doing this is really important. You may want to freeze the developments of the application for a month or two till you have a clear definition of the abstraction layer. Involve your enterprise architects, talk it over with the business.
You may want to put API management in place and even create APIs that access the Monolith database(s) directly. Now you’re ready to start the transformation.
2. Stop digging your hole.
Now, stop any developments on the monolith. That functionality is available and is no longer changed. Make sure it is called for through the APIs. This implies you may have to change things in other applications that interface with this one. What you are doing is isolating the monolith and only access it through the APIs. Any new development is done outside the monolith and interacts with it through the abstraction layer. Build the new functionality using SOA principles, or even better, go for microservices. In this case, take a serious look at the 12 factor app. Your new functionality is loosely coupled with your monolith and with other applications and functions, it does one clearly defined functionality and it is autonomous. In other words, the only interactions with the outside world are through defined APIs.
3. Replace existing functionality.
But what do you do if some of the functionality embedded in the monolith needs to be changed? This is actually where your transformation process really starts. You will carve out the functionality needing change, copy the code and transform it into a component or a microservice. In that process you will implement the new requirements of the business, but you’ll go somewhat further by extracting it from the monolith. This may imply you have to change some code within the monolith to redirect the call to this portion of the functionality. Here again, the way you designed your abstraction layer in the first place may make this effort more or less easy. See whether you can keep some consistency between the old way specific functionality was called and the API you define for the future.
By doing this you have reduced the monolith somewhat. Over time you may replace parts by own developed components, or eventually by COTS (Commercial of the Shelf) functionality. That doesn’t matter. The objective is to use external triggers, business, regulatory or actual bugs, to extract and transform pieces of functionality one at the time, emptying the monolith over time.
Obviously you will have to adapt the abstraction layer every time to point to the right functionality. It becomes a recurring process.
We can present the journey in following way:
You can initiate trunk based developments for the new functional modules during the transformation. However, every time you do a change in the monolith you will have to go through a thorough release process. Such approach allows you to start automate testing, to integrate agile development approaches in your functionality creation process. It enables you to initiate an agile and devops thinking and to initiate the cultural change that this implies.
Remove the release cycles
By transforming your application into a series of loosely coupled functional modules, not only do you enable them to scale-up and scale-down to address varying needs, but you also enable the release of individual modules, making the traditional release process obsolete. What if you no longer need to plan a release for weeks or months, have a team working around the clock over a week-end to install the new version and maintain staff on stand-by if a roll-back is required?
As the functional modules are loosely coupled, you can now just replace ONE module in the series. And if you make your modules error-proof and capable of handling the absence of surrounding functionality, you have the opportunity to bring functionality online in a matter of minutes.
Have you ever been on a website where a message like “this functionality is not available at the moment, please try again in a couple minutes”? And by the time you retry everything works. You may well have been the unknowing witness of the releasing of a new version of the functionality you invoked. Software development is in the middle of a revolution where all the principles are jeopardized and replaced by new ones. It’s important to understand where the industry is going and the advantages you can get by implementing new approaches. The abstraction layer we mention above can be provided through an API management gateway, facilitating the work of the developer. But that gateway has many other benefits. To understand which ones, read my next blog entry.