loading...
Cover image for How do you deal with legacy projects?

How do you deal with legacy projects?

madza profile image Madza ・1 min read

Most of the devs are aspired to learn cutting-edge technologies and develop new, innovative products cause it's fun and adds a lot of value, keeping them excited and inspired.

In reality, tho, the vast majority of the open roles are often seeking devs to maintain their monster-size code-bases often written in outdated frameworks to fix bugs while avoiding damage to major dependencies.

How do you keep motivating yourself to deal with continuous legacy projects? Or do you try to avoid them at all costs?

Discussion

pic
Editor guide
Collapse
andrearicchi profile image
Andrea Ricchi

My approach is usually divided into two: first I start to decipher the code like an archeologist, with a lot of WTFs and WHYs. Then, when I realize that the project is a total mess, I cry a lot until I end up with a fix that doesn't break all codebase.

Collapse
zoedreams profile image
Collapse
daviddalbusco profile image
Collapse
madza profile image
Madza Author

Hahah, this made my day 😂😂

Collapse
recursivefaults profile image
Ryan Latta

I love legacy codebases.

First riddle is how did a bunch of smart developers create a codebase like that? Are you doing anything so significantly different that you aren't leaving a legacy yourself?

Ok, now that I've ruined everyone's day lets get into it.

Legacy code is an odd animal because it generally does the job it was asked to do, but is generally hard to understand and harder to change. So, first thing I like to do is respect that this code is doing its job and someone is getting something out of it.

Most legacy codebases suffer from a problem that nobody can keep it in their head or remember what it does or how a feature behaves. Most legacy codebses don't have tests either.

You're writing tests right?

So, all you can do is accept that the code exists the way it needs to even if it looks broken or buggy. Now you need to protect that code from abberant change by writing some tests. These tests don't tell you it works, but they do tell you if its behavior changes. You need that.

With some tests you can now begin to make changes where you surgically adjust functionality while cleaning up as you go. The tests inform you that behavior is maintained as you work.

Last bit is the temptation to rewrite or start a new project. Rewrites are a disaster waiting to happen. Remember that depressing thing I said earlier? Compound that with the fact that nobody knows what this thing does and you have a recipe for a instant legacy codebase that fails to do what the other one does too.

You can implement several isolation patterns in place like the branch by abstraction or strangler to slowly but surely create a modern implementation of it. But before anyone tries this, they had better be serious about working in a significantly different way or they'll make it worse.

Collapse
kant312 profile image
Quentin Delcourt

"Most legacy codebases suffer from a problem that nobody can keep it in their head or remember what it does or how a feature behaves." 👉 That is so true 😅

Collapse
clhenrick profile image
Chris Henrick

Highly recommend reading Martin Fowler's book Refactoring. One of his main points is that refactoring code should continuously be part of the process of software development, especially when handling legacy code. He provides some great examples of refactoring, provides lots of refactoring techniques, and even addresses why its so important and how to advocate for time to do it from management. I just read this book and have found it invaluable for refactoring some code I wrote 5 years ago for a personal project. Check it out!

Collapse
chrkuhn profile image
Christian Kuhn

I picked up a project two years ago as a freelancer. An iOS and Android native app. Documentation was non existent, previous devs could not be contacted. Problem was: We needed to immediately start releasing updates. My best friend during this time was the debugger.
In the end I convinced my client to rebuild the entire app in react-native and maintain the old code until the new app was ready.
I do not generally avoid legacy applications, but I think it is important to be honest with your customer. If the code and documentation is really bad and beyond repair/maintenance, I try to convince him of the benefits of starting (at least in part) from scratch.
In my experience, trying to patch around broken projects will never make your customer happy, frustrate you as a developer and ultimately be more expensive in the long run.

Collapse
madza profile image
Madza Author

In my experience, trying to patch around broken projects will never make your customer happy, frustrate you as a developer and ultimately be more expensive in the long run.

This is well put 👌👍

Collapse
yoursunny profile image
Junxiao Shi

The stallion coder doesn't deal with legacy code. I rewrite all of them every year.
Dependants? It's your problem. I gave you 30-day notice on deprecations, and then it's removed. You are supposed to rewrite dependant code every year, too.

Collapse
sainathsurender profile image
sainathsurender

Look at those lines and lines of code inside for loops and no try catch till I reach a point where I use a punching bag to relieve all the anger and then start to think about ways like caching, splitting into services, using linq and then when you present all the finding and improvement you manager replies saying we would not get the approvals or its to risky. This is happening in one of the big 4s and killing urself is the only way out

Collapse
jonlim profile image
Jon Lim

It seems like you are asking two different questions:

  1. How do you approach work involving legacy projects?
  2. How do you deal with having to work with legacy projects?

Let me know if I have misunderstood, but I will answer the two questions that I read from your post.

1. How do you approach work involving legacy projects?

You wrote:

maintain their monster-size code-bases often written in outdated frameworks to fix bugs while avoiding damage to major dependencies.

So it sounds like you're working with poorly documented, not tested, possibly in-house made frameworks that have bugs or need additional features built. And you are thrown at the task, and expected to do the work.

I would start with a few questions:

  1. What is our timeline for the work?
  2. Given that timeline, how much time can we spend investigating / documenting / adding tests to understand the legacy code?

If the required work is more than a small bug, and the timeline is unreasonable, I definitely express that thought and push back for a more reasonable timeline, especially if it's my first time with the legacy codebase. If the timeline is immovable, and the work is fixed in scope, then I make sure to mention that this should be an exception, and that I will actively avoid or refuse that sort of work next time. (We are fortunate to be in a career that is in high demand right now, so I think we have leverage.)

Now that we know the timeline and work required, I would go through the concurrent acts of a) finding where the work needs to be done, and b) documenting and adding tests for as many places as I can on the path to the work to be done.

This allows me to solve the problem at hand, but also make the codebase easier to pick up next time someone else (or myself again) needs to do work. Even if it's as simple as "running this locally" instructions, it's better than nothing!

2. How do you deal with having to work with legacy projects?

You wrote:

How do you keep motivating yourself to deal with continuous legacy projects? Or do you try to avoid them at all costs?

The real meat and potatoes of your post, in my view, is how does one continue to develop their career positively while having to work with legacy projects. It's a great question everyone should ask themselves, if they are ever posed with the situation.

Having been there personally, there's a few thoughts I had while my team took on more and more legacy services, and having to maintain them while building out new features:

  • Opportunities to improve documentation and testing, which are important skills to build and develop as software engineers, but are also helpful for developer ergonomics should another team also want to build out features in the same legacy code
  • Opportunities for refactoring code and optimizing performance / readability in an older / legacy codebase, which is done in a much more controlled way with proper documentation and tests, and can end up saving the company time and money (through faster development, or through fewer resources uses)
  • Opportunities for project management and communication; if you are maintaining or building out legacy projects, you can get some real practice in understanding the business problems at hand, and how you can scope + plan + communicate the technical solutions you intend to build out

In the event that the above opportunities do not exist for the work you are doing on the legacy codebase, then I would communicate that your career growth is being negatively affected by the work, and ask for either additional work, or to be moved somewhere else entirely.

If that's not possible, it could be time to start looking for new opportunities.

Collapse
acro5piano profile image
Kay Gosho

Basically there are three options: refactor / rewrite / replace. In my experience you must consider refactor first, even if you want to replace whole code. If you rewrite or even replace whole code base, you must face similar issues which solved by the legacy code.

Collapse
jessekphillips profile image
Jesse Phillips

I don't have a huge list of experience to pull from.

First thing, legacy code is a great place to see all those coding practices and patterns you've been taught having fallen flat on their face.

Second, you learn how to read code.

Third, you learn what is valuable to communicate.


First off, make sure there is a good test plan in place. This could mean writing new test coverage, but it may also mean relying on a QA department.

Have a plan to get small changes into production quickly.

Look to update the dependencies. Sometimes you can't take it to latest without major architectural changes. But you don't want to be caught unable to do proper development practices because the tool you need is too new.


Fear of breaking something is going to be a huge driver for management. If you aren't able to get support to cover the development appropriately to mitigate those risks, then maybe consider bowing out.

Collapse
starswan profile image
Stephen Dicks

Simple - stop writing legacy code. Too many projects are 'on the road to legacy' from the day they were born - write good tests and enough documentation and comments (comments the WHY of code) so that the next person at least has a vague idea what you were thinking at the time. Practice TDD 'test-first' so that your tests describe your system's intended behaviour at an appropriate level of abstraction (i.e. not all unit tests, that just demonstrate that a component meets it's public interface)

Collapse
dmahely profile image
Doaa Mahely

When I started working with a huge legacy codebase, it was very normal to spend an entire day just reading the code and trying to understand the flow. A year later, I’ve gotten a lot better at it, but sometimes I still find myself dreading to make big changes to the pile of spaghetti code that might break something or everything.

Collapse
richardhaven profile image
No Clever Code

"an entire day" ‽

I've spent weeks inventorying code (while also working on new features, granted)

Top-down coding lost its cachet in the '80s, but it's the best way to avoid creating "legacy code": instead of a big mess of spaghetti, at worst one makes lots of little bowls of macaroni, which one can refactor individually

Collapse
richardhaven profile image
No Clever Code

First, inventory the chucks of code, find dependencies, review recent bugs, and come up with a list of areas for possible refactoring. Do a few small test refactors to learn how much it costs (learning the build process, causing "unrelated" failures, etc.)

Then present a list of refactoring candidates comparing their estimated costs and estimated benefits (e.g. foreseeable enhancements, criticality). Include a plan to compare actual costs for refactoring and estimated costs for not refactoring with your plan

Then it's a management decision

Collapse
aminmansuri profile image
hidden_dude

You say "legacy" as if it was a bad thing. It CAN be a bad thing.

But it can also mean that the project has been a success for years or decades even.

If you're working on the Windows OS, or Office, or Linux, or GMail those are all "legacy" codebases. They're also some of the most successful software projects of history.

I've dealt with new projects and "legacy" projects. I tend to look at them much the same way. Often I'm more concerned with ADDING VALUE TO THE BUSINESS than worrying if they are "still" using this or that.

A "legacy" system is often a PROVEN system. And many times has a lot of value, an rewriting it is going to be extremely costly or impossible.

Old projects can involve innovation as well.

I'm surprised by how many people commenting here mention rewriting or replacing. Maybe they are confusing "legacy" with "failed".

But in general you want to find a way to ADD VALUE to END USERS and avoid rewriting code that has worked for years or decades.

Collapse
dominikbraun profile image
Dominik Braun

Depends on how old the codebase is and how the development process lookes like. I'm willing to improve and refactor a code-reviewed, tested, active codebase - but maintaining a 12-year-old codebase without code reviews and version control has been a real struggle for me.

I only see two ways of avoiding such a state:

  • Continuous refactoring in short cycles (feature branches can prevent this, though)
  • Splitting up the codebase into standalone microservices that are re-writable within 2 weeks.
Collapse
csgeek profile image
csgeek

Microservices is usually the path forward. Monolithic code bases are insane. Nobody can do anything in there and splitting code makes everyone life easier.

It does involve software architecture to understand what is going on and having a path of switching traffic from one path to another. A/B testing would be ideal.

Hope this helps.

Collapse
loouislow profile image
Loouis Low

It's so easy to do it these days. I dockering them so that they survive as long as they could. For example, I used to create an application for my uncle's clinic. It was 13 years ago, I was 27 at that time. The application has still been using until now. Over time, technology outdated so quickly. I was using LXD to contain them in a legacy environment. Then, the second attempt was using Docker.

Tada! Meet my very nostalgia creation...

screenshot

screenshot

screenshot

Collapse
olivierr68 profile image
OlivierR68

I was in this situation not long ago, with a homemade framework with no documentation, a lot of variable abreviatated names (like $v, $d, $c) and method, no autoload (lot of require) and other old stuff.

What i did was just to dive into it. Even if i didn't like it and i was often irked at how the framework was made. It get better the longer you are in it, you also learn a lot about the language in general (php in my case), and you should and should NOT code.

Collapse
zaffja profile image
Zafri Zulkipli

My approach is to just make necessary changes and prays it does not break anything (literally). There's even a bunch of files with 6k line of code and everybody relies on that and since the old devs have resigned, we're just basically coding while hoping for the best. Right now we're in the midst of migrating all the important features so hopefully we can finally shutdown the legacy system.

Collapse
djnitehawk profile image
Đĵ ΝιΓΞΗΛψΚ

either avoid or convince them to rewrite with something modern and maintainable. life's too short to wreck my brain with someone else's choices they made 10yrs ago 😋

Collapse
peter279k profile image
peter279k

At first time, it looks awful for me.

After above times, I try to improve them about reliability, flexibility and scalability.

Collapse
kushalkant profile image
Info Comment marked as low quality/non-constructive by the community. View code of conduct
Kushal kant

No one touches the legacy code. I update all the code timely.

hello@freelanceruidesigner.com