The Dark Side of the Legacy Code in the Rails' Monoliths
Any good solution is valid only for a certain time frame. For a startup, investing millions in software development is not advisable. So very often everything starts with an MVP, the costs and terms of development of which are very tight because, in a couple of months, competitors will be ready to copy all of your best developments. But when a startup finds its niche and grows into something bigger than just a “good idea”, it suddenly turns out that what worked great at a low start might not survive the marathon.
After all, a monolithic application is a kind of atavism for a system of complex modern projects. Changing the architecture of a live solution is not an easy task. This article is about the dark side, legacy code, and practical steps to solve the problems with monolithic applications in Rails.
The main reasons for the appearance of legacy code:
- New versions of programming languages, operating systems, browsers, gems are constantly being released. And each new version requires fixing compatibility issues with third-party code. This cannot be avoided. Separately, it is worth looking into the issues of interaction with systems that have ceased to be supported. It usually happens that some technology becomes hype and everyone abruptly begins to add it to their projects, but 3-4 years pass, and it “dies” for one reason or another, but the necessity to maintain the functionality of the modules implemented with its help remains.
- Technical debt piles up during the life of the monolith. It starts with a limited budget and an “invisible” for the client code that ensures the operation of the system. There are monolithic applications, some of the logic of which is designed and written on unsupported or rather, outdated technologies, but it works. A dilemma arises when they want to make changes to this module: is it okay to rewrite all the module’s logic or add another piece of legacy code? Can you guess what the client chooses in 95% of cases? What’s the point of redoing and paying engineers to rewrite an already working functionality? A year, two, three years pass... But as the amount of code grows, development slows down; it becomes more and more difficult to find someone who would want to support it. Such monoliths steadily pass into the hands of a new team in a year or two, acquiring an ever-increasing load of undocumented and fragile code. In stable organizations, there is usually a deadline for retiring old software and updating it. Only the software that is protected from interactions with the outside world can work for many years without updates. For example, in ATMs and stable isolated services.
A bad code doesn’t always create problems. Only those who have never worked with it do not curse at WordPress. Nevertheless, more than 30% of the existing websites are built on it, and more than 500 new ones are created every day. According to the latest data, in 2021, 62% of the top 100 fastest-growing companies in the US (Inc. 5000) use WordPress.
So how to deal with a problematical monolithic application?
Step 1: Documentation
In fact, the majority of hard-to-fix problems are caused by undocumented code with atypical, not obvious logic. And there can be one solution to this: write the documentation and read the documentation. And the sooner you start, the easier it will be to figure it out.
You need to understand how the current system breathes, what its logic is based upon, and what constitutes its basis.
Step 2: Testing
When you have figured out the architecture and logic of the work, you can proceed to the testing. Before starting to work on improving the functionality, you need to make sure that the main functionality work is thoroughly automatically tested. If there is no automated testing in the project, you need to start with writing tests and drawing up a test plan. After all, major code changes often cause unexpected problems. You need to prepare a plan and work out a mechanism for releasing new versions with the ability to roll back to the previous one.
Step 3: Update the language version
A few years after writing, the code becomes incompatible with the current version of the language and leads to a whole bunch of problems. As the coding continues, the updating must also continue to help eliminate vulnerabilities and avoid a lot of possible problems in the long term.
To develop new products, you need third-party libraries that require an up-to-date version of Rails. Also, in older versions, bugs are not fixed. It is more difficult to find developers for a project in an outdated version of the language. As a result, the cost of solving problems based on existing software grows, and more efforts are needed to maintain performance.
Step 4: Take out the scalable modules from the monolithic application
With the growth of the project, the complexity of the software grows. The functional content expands and, along with everything, the amount of code is constantly increasing.
According to the customer’s requirements, create a list of functionality that needs to be scaled, and move it into separate modules.
Working with a large monolith is not an easy task. But the described steps will help you eat the elephant piece by piece and make a large application less complicated.
If you need qualified help and support, our team is ready to help you.