StranglerApplication pattern: a legacy frontend use case
Or “how we transformed an AngularJS application in a shiny new Frameworkless application”
What makes a codebase “Legacy”? I think that there’s no unique answer to this question. Most people associate the idea of legacy code to the fear to modify the code. It could be the absence of tests, obsolete tools or other factors. But I think that there’s something more. A good visual representation of legacy code is a cage.
Why a cage? Because I feel legacy code is something that can hinder the evolution of a software. In other words…
Legacy code is a roadblock to adapt software to new business needs.
Let me share with you a story.
In 2013 we started a new greenfield frontend project. We chose to use AngularJS, and it was the right decision to make.
It was a good decision.
The software, at the time, was part of an experimental business. Neither our client nor our team knew if users would be interested in that software. And when you are developing a software for an experimental business your most important non-functional requirement is to have quick feedback. AngularJS at the time was a de facto standard for the JavaScript community and it helped us to have the velocity needed to bring the software to the market as soon as possible.
Let’s jump now four years in the future. it’s 2017 and the software is a success. Most of the income of our client derive from this software. Another thing changed in the meanwhile: AngularJS died.
Angular being dead was not a problem per se. It was a problem because our business context changed drastically and our non-functional requirements changed with it. Velocity it’s not our top priority anymore.
Our greatest concern right now is the Longevity of our codebase
When we realised that our context changed, AngularJS transformed itself from an asset to a liability. Or, if you prefer, it became a cage.
When we realised that, we made a very important decision.
We decided not to use AngularJS from the moment on, and in order to keep our longevity at the maximum level possible we decided not to use another framework.
But how can we do that with our application currently in production?
A cut-over rewrite was not an option. It would take at least a year to release a frameworkless version of our project, and this scenario was not acceptable by our client. So we came up with a more feasible approach, the StranglerApplication pattern.
To apply this pattern, a new application is created. This new application will slowly replace (or strangle) the old one, until the old application is so small that you can safely remove it.
In our specific case the old application was AngularJS web application built with Grunt, and the new one is a frameworkless application built with webpack.
After the creation of the new application we imposed ourself a very simple but strict rule: no commits on the old application. Every new feature should start in the new part of the application, and every change request or fix to the old part should start with the porting of the old code in the new environment, adapting it.
In this post I will not go in detail about the code part, I will just say that:
- we converted every
service
to a standardES Module
- we converted every
controller
ordirective
to acustom element
- every
ES Module
is accessible by the old part as a service using a simple bridge function
If you are interested in more details about how to implement this kind of solution for your project you can checkout this GitHub example. In that repo it’s possible to see how, with every commit, a piece is moved from the old application to the new one.
I’ve also talked about this topic at JS Day 2018 in Verona. In the talk I explain briefly how the bridge function is designed.
My talk at JS Day 2018.
What we Learned
We learned a lot from this refactoring. The first and probably most important thing is perfectly summarised by this quote from Gerald Weinberg.
Don’t be rational; be reasonable.
What I mean is that when we first tested this solution during an Architectural Clash, we felt that it was too “strange” to really work in production. But we decided to give it a try and we loved it. Ideas that seem “not right” but that are good enough for your context, need to be explored with some experiment before deciding that they are really “not right”.
Another thing that we learned the hard way is that strangling a web app is a very long and laborious process. So when we design a new piece of software we try to design it in a way to make it easier for it to be strangled in the future. One of the principles that we adopt is the Sacrificial Architecture always by Martin Fowler.
At last we learned that working without frameworks on the frontend is completely doable with the right people in your team. From this experience we decided to create the Frameworkless Movement: a group of people interested in developing without frameworks and helping everybody make mindful technical decisions.
If you want to talk about StranglerApplication pattern, legacy frontend applications or the Frameworkless Movement just contact me on Twitter, my DMs are open.
Update: I talked about this topic at JSDay 2018 in Verona, you can see the video of my talk here:
If you liked this post, you can buy me a virtual coffee ️😊