Legacy code - a fairy tale for (un)polite programmers?

Blog post image

Once upon a time, a long, long time ago, a King learned that his subjects could work better and bring more benefit to the kingdom if they had a System that would streamline their work. So a council of Sages was convened and a Document was created in which each of them wrote what they wanted. This, in turn, was handed over to the Great Manager, who summoned the Programmers and said - Here you have a plan. Now get to work! It has to be ready by yesterday!

The programmers locked themselves and the Document in their, quite comfortable by the way, dungeon. They began thinking, tapping their fingers on their keyboards and thinking again. Their vats of hot coffee and supplies of pizza and hamburgers were replenished on a regular basis. After a few weeks, the Big Manager was finally able to show the King their creation - the System. Everyone liked it right away, it was pretty and everyone was going to find it very useful. He was even given his own chamber in the castle and fed data regularly. Actually, this tale should end with the sentence: "And they lived happily ever after." Unfortunately, as it happens in life, the finale was not so obvious. It turned out that the System had to be taught things that even the greatest Sages had not dreamed of before. So the programmers and the Sages themselves changed the System more and more. They added more legs, tentacles, additional heads or tails to it. Slowly it became uglier and uglier, bigger and occupied more chambers and floors of the castle. Until finally it became so huge that it almost didn't fit in. Its creators fled the kingdom, although there were also rumors that the System had devoured them. And the System grew further and slowly turned into a horrible Monster that no one liked or cared about anymore.

Sooner or later, every programmer in his career will come across a project in which he will face such a Monster.

Legacy code (legacy or stagnant code), is code that has been in production for some time. It is created by people who are no longer present in our organization or external companies that no longer exist in the market. Very often such code has no documentation, and the initial assumptions have undergone many changes during its operation. For a variety of reasons, you will also find no unit or integration tests, or tests written earlier as a result of too many changes and the introduction of additional dependencies are no longer reliable.

Actually, all programmers love to hate legacy code. It's not beautiful, it doesn't have modern and "trendy" technologies, and it doesn't allow us to do "creative" work. However, it is important to remember that eventually any code will become legacy anyway. It's a bit like the human organism. It develops, ages, and if we don't take care of it, and don't keep it in proper shape, eventually it starts to get sick, and over time refuses to obey. So, if even initially such code was really well designed and written, now it can look like the famous Frankenstein's monster sewn together from dozens of pieces. Working with such code, despite the many difficulties we will encounter, does not have to be a curse for the programmer at all. Such a project gives us a chance to learn the basics of programming, use proper techniques, design patterns, write clean code and good tests. 

What to do. How to live?

0."Erem terem tytyrytki, perish, monster, for thou art ugly!"(S.Lem Cyberiad).

Unfortunately, in the case of thelegacycode monster, this spell rarely works. However, the temptation is great: isn't it better to write everything from scratch? Sometimes yes. However, it always has to be a well-considered decision supported by detailed analysis. Without knowledge of the system, how it works and the dependencies between functionalities, it is better not to undertake this task. And with a production-operating system, it may simply not be profitable. 

1 Make friends with the Monster.

To effectively and safely maintain or change a legacy code system you need to know how it actually works. Given the aforementioned lack of documentation and new functionality added, sometimes over the years, this is quite a difficult and time-consuming process. Sometimes there is nothing left to do but "crawling through" each method or class and debugging the code line by line. Quite effective in such a case is the so-called scratch refactoring, which consists, in a nutshell, in copying the production code to a separate project, a kind of sandbox. There, refactoring is then carried out, tests are written, and we check how our Monster will behave when we cut off one or another tentacle. Such refactoring allows us to quickly and efficiently learn the dependencies that exist between system components, without the risk of messing up anything in the production code. The most important thing about this method, however, is that all of these changes MUST be removed. Of course, the knowledge gained can and should be used! I know from experience that without knowledge of how the code works, it is very easy to improve one thing and mess up several others.

2 Fantastic Animals and how to take care of them.

When, in the course of tweaking old or introducing new functionality, you learn about the legacy code, write down what you've learned. Create and update code documentation - even the smallest piece of knowledge can prove invaluable in the future. Also, try not to keep this knowledge just for yourself. Remember that the so-called"BUS FACTOR" in a project should always be greater than 1. In a somewhat macabre translation, it determines the number of team members who must be "run over by a bus" so that the project cannot continue. So if in our project the "bus factor" = 1, it means that a random accident, illness or simply the decision to continue beyond the project of this one and only employee will result in there being no one to reign over our Monster code.

3 Train the Monster whenever possible.

Testing is, so to speak, taming our beast. Writing tests when making even the smallest change, using TDD (Test Driven Development), will eventually lead to a point where most of the code is covered by tests, and its maintenance and implementation of subsequent changes will be much easier and safer. What's more, by writing tests you will be able to better understand how the code works. This approach should become a habit and the first thing you do. Paradoxically, there are cases when the complexity of the code is so high, and our knowledge of how it works so low, that it is very difficult to write meaningful tests. Maybe this is where there is room to write the functionality in question completely from scratch?

4 Refactoring - nurturing monstrous code.

Improving the structure of the code itself, in order to make it more understandable and cheaper to maintain, without at the same time changing its operation, that is, refactoring, is the equivalent of a coat brush and claw clippers when it comes to monster code. We often have to accept that not all ideas, even the best ones, can be put into practice right away. But we can, and should, sometimes make even small changes to the existing code so as to leave it in a slightly better state each time. Leaving the code as it is, on the principle: "If it works, don't move it!" is not a good idea in this case. Changing business models, standards or laws in a country sometimes force us to make changes in quite a wide range. Such an example is the changes in data protection regulations (RODO), which have necessitated the modification of many systems that process this type of data. When implementing new functionality, try to keep the code "clean" and keep it that way. Let's not add more "monstrosities" to the ones we already have! Above all, however, as the famous Hitchhiking Guide to the Galaxy advises - don't panic! After all, the code you're dealing with sometimes even worked flawlessly in production for a long time. Besides, tell me honestly, haven't you ever found yourself looking after some time at your own code written months ago wondering, with horror, "Who actually wrote this!" So instead of complaining about how monstrous the code you are about to face is, try to make it really fun, which by the way will be a lesson for the future. Someone once said that if you do what you like, you won't work a single day in your life. Which remains to be wished for all of us.

Related posts

All posts
Blog post image


Revolutionising the insurance sector: how to outperform your competitors

Technological advancements are reshaping traditional practices and revolutionis...

Read more
Blog post image


The basics of dockerization in .Net Core

So where to start? Experience tells me that the initial entry threshold is rath...

Read more
Blog post image


Biased lock off - again!

This article describes selected JVM tuning issues using selected JVM flags. The...

Read more