Profile    Mohammed Shiroz Status   Loading  
Logo
Share This
Back to blog
Filter by:
Tags
//Article title

Me vs the Legacy Codebase: A Week in Five Acts

About Post

Every developer meets The Legacy Codebase eventually. It's usually introduced with a nervous laugh and the words "it works, mostly". What follows is a week that I'm fairly sure every one of us has lived through at least once, in some form. Names have been changed to protect the functions.

Monday: first contact

❌ You open the project. The main controller is a single file you have to scroll for a long time. There's a function called processData2. There is no processData. There is, however, a processData2_new_FINAL.

❌ The test folder exists. It contains one test. It asserts that true is true. It passes, which is the most reassuring thing you'll see all week.

❌ You find a comment that says // don't touch this. seriously. git blame points to a commit called "initial import".

By lunch, a thought has arrived, fully formed and glowing: "I could rewrite this whole thing properly in a few weeks."

Tuesday: the urge grows

❌ You sketch the new architecture on a whiteboard. It's beautiful. It has layers. It has a diagram with arrows that all point the right way.

❌ You start a new repository "just to explore". You name it something hopeful, like v2.

❌ You change one small thing in the old code to fix a bug. Three unrelated screens break, including one that, as far as anyone knows, isn't linked from anywhere.

Wednesday: the code fights back

❌ You discover the "weird" rounding in the invoice calculation isn't a bug. It matches an agreement with a client from years ago, and finance depends on it. It isn't documented. It's only in the code.

❌ The function with seven boolean parameters, calculate($x, true, false, false, true, null, true), turns out to handle a dozen real edge cases, each one a lesson somebody learned the hard way.

This is the moment the legacy codebase teaches its most important lesson: ugly code is often ugly because it knows things. Every strange if might be a bug fix. A rewrite throws away all that knowledge along with the mess, and then you get to rediscover it, one production bug at a time.

Thursday: the grown-up plan

So you close the v2 repository (gently, it did nothing wrong) and do the things that actually work.

✅ Write characterization tests first. Not tests of what the code should do. Tests of what it does right now, weird rounding and all. You feed it real-looking inputs, record the outputs, and lock them in:

public function test_late_fee_matches_current_behaviour(): void
{
    $invoice = ['rent' => 1000, 'days_late' => 12, 'discount' => 5];

    // Recorded from the existing code, not from the spec
    $this->assertSame(1049.5, (new LegacyInvoiceCalculator)->total($invoice));
}

Now you have a safety net. If a refactor changes a result, a test tells you before a customer does. If the behaviour really is a bug, you change the test on purpose, with a note explaining why.

✅ Use the strangler pattern. Named after the strangler fig, which grows around a tree until it can stand on its own. Instead of one big rewrite, you build new pieces next to the old system and route traffic to them one feature at a time: the new invoice endpoint first, then reports, then the next thing. The old code shrinks while the app keeps working, and you can stop at any point with something useful.

✅ Refactor what you touch, not what offends you. When a ticket takes you into processData2, leave it a little better: extract a function, name a variable, add a test. Over months, the busy parts of the code get clean, and the parts nobody touches stay ugly but harmless.

✅ Add logging before changing behaviour. Not sure if that mysterious branch ever runs? Log it for a couple of weeks. Data beats guessing.

✅ Write down what you learn. The rounding rule, what "don't touch this" was protecting, the reason for the seven booleans. A short note in the repo saves the next person their own Wednesday.

Friday: acceptance

The codebase is still old. But it has tests now, the new piece is live alongside it, and you've stopped flinching when you open the main controller.

You also notice something uncomfortable: some of the code you wrote a few years ago is now someone else's legacy codebase. Somewhere, a developer is opening your file, finding your helper2, and having their own Monday.

The useful bit: legacy code is code that makes money and has no tests. Add the tests first, then change it in small, reversible steps. "Rewrite it from scratch" is almost always the most expensive way to learn what the old code already knew.

What's the strangest thing you've found in a legacy codebase that turned out to be there for a very good reason?

Comments (0)
Leave your review

Thanks for your valuable comments. Your comments has been updated and appreciate your getting in touch...

01. About Shiroz

Mohammed Shiroz

Hi, I'm Mohammed Shiroz, a software engineer and AI enthusiast from Sri Lanka who turns ideas into intelligent, real-world solutions. With over 9 years of hands-on experience, I currently lead real estate ERP development at Kate Group, a...

03.My Projects

04. Categories

Ready To order Your Project ?

Get in Touch
Close