Legacy code — keep your sanity

Published on

image

Photo by Matthew T Rader on Unsplash

First published at https://rghiorghisor.medium.com/legacy-code-keep-your-sanity-8707dcc2ba13

In this article, I am not trying to provide any technical tips for handling an old project. It aims to offer a few ideas to follow if you want to keep your sanity while being assigned a legacy project. We are going to take a look at what roughly makes up a legacy and try to find why it may not be as bad as it looks at the first glance.

On the other side, I am hoping not to fall into any motivational advice. I am not the one to say how one should feel while working on what. What makes you happy is up to you. But taking part in legacy projects does not always have to be the browbeating part of one's job.

My relationship with legacies is one of those love-hate relations, going from enthusiasm to considering my life choices and back real fast. During my career I had to work on some old, outdated, or “how is this still alive?!?” produces and each time I got myself into such a project I could not but be enthusiastic and intrigued at the same time. I knew that the outdated technology, business needs and restrictions will be hard to navigate but also taking over such a project may provide as many challenges as starting a brand new one, if not more.

A legacy project is one of those systems that didn’t or couldn’t keep up with technology advances and coding modernization, but its business revenue is still relevant to the company and the fear of change freezes any of its advances. As that was not enough, usually they are accompanied by faulty documentation (if any) and lack of shared experience or any type of testing. Another integral part of these projects is the low morale of people handling them.

If you look for some more in-depth analysis, in the Defining Legacy Code article, Eli Lopian presents some very interesting takes on what exactly makes a legacy code, from “It’s Code That Developers Don’t Like” to “It’s Code That Is High-Risk to Change”.

I feel that sometimes engineers, blinded by the lights of modern technologies, lose sight of what knowledge and experience can be pulled from older projects. So let’s try to seize some of these crucial issues and investigate some tips that hopefully will soften the criticism and make one’s work-life a little bit better.

Outdated technology — It’s not the end of the world!

Working on a legacy system is not exactly the worst thing that can happen in your professional career, so try to avoid treating it as such. Depending on the project, one might find that the long term experience gain is significantly larger than working on a new project with brand-new technologies. Granted, this may be unclear from the beginning but I think that any project has its hidden gems.

Most of the newer and popular technologies were created as a response to developers’ needs, but that does not mean the old approaches are obsolete. Furthermore, adopting or learning these new technologies is much easier when you know the basics, basics that are usually present in legacy codebases in one way or another.

Let’s take a look at Object-relational mapping. These sorts of tools have been popularized by the need to better handle database access, eliminate boilerplate code, and provide standardization of database entities organization. Needless to say, they caught on very well, so much that we cannot think of developing a brand-new application with database access without having an ORM. But adopting such tools does not render mute the need for SQL knowledge. After all, an ORM still uses queries and techniques that have been around for a while, but it does it implicitly with little to no interference by the developer, besides the initial configuration. Therefore experience with, now defined as traditional, database access is still needed and this experience will definitely come into play when you will stumble upon ORMs.

As one would expect, many more examples can follow: web frameworks, build tools, or programming frameworks.

All things considered, what I am trying to say here is that even if modern tools are not present in your project, that does not always lead to terrible outcomes. When you will face new and (maybe) sophisticated technologies, the low level approaches learned here will benefit you greatly in understanding how these wonders work.

Old codebase — Don’t despair!

While working on legacy code, the most notorious way of breaking down that I have noticed is developers not writing the best code to their ability, because they see no reason, as the quality of the code they are working on is already bad. “Don’t worry about writing code, it’s already crap! I just have to make it work” is a phrase that I find myself continuously fighting.

One of the most (dis)honorable examples of giving up is not writing unit tests because the functionality that should be tested is just too big, and there are no tests anyway. But not writing tests, not only will make refactoring much more unlikely but will equally make your work blend in with the awfulness of the existing code.

Let’s see why handling work in a professional manner is still important in such projects.

Code quality is still important for codebase development.

Clean and maintainable code is not merely for aesthetics purposes. A well-organized code will influence the maintainability and, in some cases, the performance of the application, among many others. Thus, writing good and clean code will benefit the overall codebases, despite how the other parts look and feel.

The code you write and work you do is still your calling card, despite the project you add it to. When taking a look at your code, the context in which it was written does not matter, but how it looks and runs.

It is highly possible that after some time (months, days, or even hours) a glimpse of your work may be embarrassing even if you tried to do your best. Imagine how you will feel if you purposely don’t care about code quality.

Giving up will have medium to long term effects on personal development.

Not doing your best every day will eventually affect your overall performance. And I am not talking about how the company perceives you, but how your abilities will be affected after some time by this atrophy. Not trying to find the most elegant solution to issues, being afraid of implementing modern strategies will make your life harder in the long term.

And this attitude does not have an on/off switch as many of us would like, and once gone on that road turning back will become harder and harder.

Other’s morale will be affected.

Your barely the minimum job will not only affect you but also your colleagues. Imagine having a junior developer taking a look at the code that “only works,” you just wrote. They might be inclined to carry out the same sloppy job.

Fear of change — Fight it!

The main reason for legacy systems to still be around is the fear of change, and this fear will manifest at any level of the organization. Developers being anxious about refactoring their own code makes the codebase obsolete, team leaders not changing development paradigms affect morale, managers not supporting feature changes leave the project in a state where the only stamp it can be applied to is the dreaded legacy.

Updating the application may bring unwanted risks and, in the eyes of some decision-taking factions, the best way of going about it is just to keep the application going until it will die on its own or it will become someone else’s problem. But of course, that moment will never come.

But you, the engineer with legacy dirt on the hands, may have a different stance on this. If you think the system needs to die or needs a major rewrite, you should communicate that to the proper people in the proper manner. Please don’t fall into that “it’s not my job” or “the other person must take care of this”. After all, the reason why you read this article is that you don’t feel that great about working on the project, thus imposing change seems like a logical direction.

There are many ways in which you can make your voice heard, but stating what to you it’s obvious will not make it obvious to everyone. That is why you must communicate it very well. Some pointers that helped me in the past are:

  • Why is a change needed? Why should the company invest in such a change and what are the advantages and, more importantly, the disadvantages of bringing these changes?
  • What is the plan? A timeline and the resources needed are a must;
  • What have you done in order to ease these changes? While doing your daily work have you made efforts to decouple the system from other dependent ones?

As one would expect, this might not go as well as planned. You can put in place the soundest arguments and plans on your own time but still won’t obtain the approval. That happens, and you must not feel terrible as you did everything you could in those situations.

I don’t what to trivialize the relations and communication that go into trying to make a change. There are a lot of things to take into consideration and developing these communication skills is a must in software development.

Having the opportunity to find solutions to such a complex issue of modernizing a major component and fight to get the job done may not be something you can easily find anywhere else.

Low morale — Don’t throw blame around!

I have seen this too many times. Developers being, for some reason, angry at one individual or entire teams of engineers for not implementing a proper application or feature.

Frustration in the workplace is not an uncommon feeling. But to improve your work-life, these feelings must be communicated and with the right people, a proper solution must be found to address them. If you are experiencing frustration due to modest pay, a raise might be the solution. But if you are vexed due to what others did in the past, there is not much that can be done.

Letting these sort of feeling affect you leads to a few undesirable challenges, whose effects will be extremely hard to counter:

  • The frustration will cause each decision taken by early developers to be considered by default wrong. Seeing harmful things everywhere is not a good sign and will influence the way you look at things. Trying to rewrite a piece of code because it is presumably wrong, when in fact it is just a result of the time it was written in, will cause more frustration and more time being spent on assignments that will not improve the overall project;
  • Your colleagues, especially less experienced ones, will slowly adopt these raging opinions. When a single individual is angry is one thing, when the entire team is furious that can be an issue;

Some of these feelings are understandable, some aren’t. However, we are trying to improve the project, even a legacy one. That is (should be) our purpose as engineers. I strongly consider that this must be the focus while working on such projects. Looking for the guilty party does not help in any way.

Don’t forget to congratulate yourself and the team whenever progress is done.

Fear of change — Don’t encourage it!

All subjects that we have depicted above exert an additional effect. Not worrying about code quality or not expressing any desire to improve the project’s future will further accentuate the state of fear, freezing any eventual progress.

Like it or not, the stakeholders must be assured that any change can be accomplished by you or the team. That means that iterative progress must be made and presented periodically. Some (very few) examples include:

  • Testing can be done alongside the maintenance work. I am sure that convincing the developers to write unit tests will be considerably harder than convincing the managers that time must be allocated for tests;
  • Tests will assure a much better safety for refactoring. Better than having no tests at all;
  • Introducing best practices that can be adopted for any new code will improve not only the overall codebase but the morale of people involved.

Once more I must emphasize the subjectivity of each case. Doing all of these may or may not bring any project life decisions, but not doing any of them will surely lead to no change.

From the aforementioned Defining Legacy Code article, a very clear conclusion can be drawn, that I myself totally agree with:

Legacy code is code you’re afraid to touch. So, the secret of avoiding legacy codebases is to build them in such a way that other developers are never afraid to change them.Thank you for reading these words. I know that in general there are very few things that can be said to alter your opinion on the project you work on but, hopefully, some of these situations will give you a different view of the great work you are doing.

And, as final words, a conclusion that may not be considered a general consensus: As professional engineers, we are still responsible for the quality of our own work, despite the conditions. Just as well as temporary fixes will become permanent fixes, be sure that the not-always-optimal conditions, the external pressure for working faster will always cast their shadow on our keyboards.