Testing & Code Quality

Why Does Legacy Code Always Get Blamed? A Story Every Developer Can Relate To

I can still vividly remember my first day at a new company, when I received the repository and opened the code for the first time.

4 min read
Cover image for Why Does Legacy Code Always Get Blamed? A Story Every Developer Can Relate To

I can still vividly remember my first day at a new company, when I received the repository and opened the code for the first time.

One 3,000-line file had every kind of logic tangled together. I sighed before I even realized it.

“Who on earth wrote it like this…?”

But a few months later, a new hire was looking at my code with exactly the same expression. That’s when I realized legacy code isn’t something you can blame on one person.

Here’s the conclusion first.

Legacy code gets blamed not because the code is inherently bad, but because the context in which it was written has been erased.

Today, I want to share my experience of why legacy code so often becomes the target of resentment, and how to get through it with fewer injuries.


What Is Legacy Code? Is It Different from Old Code?

Let’s establish this first: legacy code isn’t simply “old code.”

In my experience, there’s one defining criterion: code that feels too risky to touch because it has no tests.

Michael Feathers defines legacy code as “code without tests” in his book Working Effectively with Legacy Code. Even if it was written only a week ago, if the lack of tests makes your heart race every time you change it, it’s legacy code.

Conversely, even ten-year-old code is easy to modify when it has thorough tests.

So age isn’t the issue. The key question is whether you can be confident that touching it won’t break something elsewhere.


Why Does Legacy Code Always Get Blamed?

After organizing the reasons, I found three major ones.

1. The person who wrote it is no longer at the company

There’s no one to ask why it was written this way. Without comments or documentation, all I have left is the code and my imagination.

2. The context has disappeared

Most strangely tangled code has a story behind it: an urgent deadline, a bizarre requirement, or a workaround for a bug in a specific OS version.

It may have been the best option at the time, but those circumstances don’t remain in the code. Only the result survives, so it makes no sense when viewed today.

3. Everyone else’s code naturally looks strange

Honestly, this is the biggest reason. My own code feels natural because I already know its flow, while someone else’s code requires me to trace that flow from the beginning.

That frustration comes out as, “Why did they write it like this?”

Let’s look at the code below. At first glance, it’s a classic legacy-code trace that makes you wonder why such a condition exists.

// No one knows why 30 is subtracted
if user.type == "B" && amount > 0 {
    finalPrice = amount - 30 // 2019-year promotion leftover?
}

There’s no way to tell whether this - 30is still needed or is a remnant of an old event. Lines like this pile up until they become legacy code.


So How Should We Deal with Legacy Code?

When faced with unfamiliar legacy code, it’s natural to want to “rewrite everything,” but there’s a better way.

I follow three principles now.

  1. Don’t rewrite it recklessly — Working code contains countless bug fixes accumulated over time. Rewrite it, and you’ll have to rediscover all of them from scratch.
  2. Add tests before making changes — Once the current behavior is locked down in tests, you can immediately see what broke after the change.
  3. Leave a record of why you changed it — If you explain the reason in a commit message or comment, the next person will at least resent me a little less.

The third principle is especially important. It’s the only way I know to keep the frustration I’m experiencing now from being passed on to someone in the future.


In the End, Today’s New Code Is Tomorrow’s Legacy Code

What I realized over six months is a little disheartening: the code I’m carefully writing today will become legacy code that someone complains about years from now.

Accepting that made me feel more at ease. Instead of striving for perfection, I changed direction toward making things easier for the next person.

If you’re sighing over unfamiliar legacy code right now, take a moment to remember that the person who wrote it was also doing their best that day. Then quietly start by adding tests. It seems to be the way to hurt each other less.