Understanding Decades-Old Code: Part 2
Hey everyone, Jamie here.
In Part 1, I talked about the human side of joining a small, tight-knit development team. My first week was all about building trust, listening more than talking, and showing respect for the team's history. I've fixed a few minor bugs, learned the deployment script, and I'm starting to understand the “why” behind their workflow.
Now, with that initial social foundation in place, it's time for the next, far more daunting task: understanding the codebase.
This isn't a modern, greenfield Laravel project. This is a “living fossil.” It's an application that has been successfully running and evolving since before “framework” was a common word in the PHP world. We're talking code with history—decades of it.
This process isn't software development in the modern sense. It's technical archaeology.
The First Look: “Where Is Everything?”
When you first git clone a modern project, you have a map. You have a composer.json to see dependencies, a routes/web.php to see entry points, and an app/Http/Controllers folder to see the logic. You can orient yourself in minutes.
Opening this project felt... different. There's no composer.json. The entry point is an index.php in the root directory, filled with a sprawling switch statement based on a $_GET parameter. Dependencies are managed by include_once statements. Logic and HTML are woven together in the same files.
My first reaction wasn't judgement. It was a genuine, slightly awestruck, “Wow. How do I even start?”
This code is from a different era. It was written before PSR standards, before namespaces, before modern OOP was the default. And most importantly, it works. It has successfully run the core of this business for years. My job isn't to mock it; it's to understand it.
To do that, I've had to throw out the modern playbook and adopt a new, forensic approach.
Strategy 1: Follow the Thread
You can't understand a 100,000-line monolith all at once. You have to trace a single path, like following one thread in a massive, tangled tapestry.
My approach was simple: I picked the most basic, non-critical feature I could find—the “contact us” form.
I opened the contact page in my browser, looked at the URL (/index.php?page=contact), and found the corresponding case 'contact': in the main index.php file. From there, I followed the include statements, file by file.
- I found the file that rendered the HTML form.
- I found the
if (isset($_POST['submit']))block that handled the submission. - I traced the variables as they were built into an email and sent using the old
mail()function.
This simple, 20-minute exercise was a breakthrough. It taught me the fundamental architecture: how a request is routed, how page logic is included, and how form data is processed. I didn't understand the whole application, but I understood one complete slice of it.
Strategy 2: Follow the Money
After tracing a simple path, the next step is to trace the most important path. In any business, that means following the money. Whatever the core function is—processing a sale, generating a report, (or in my past life, aggregating supplier data)—that's the code you need to find.
This is the “sacred” part of the application. It's the most complex, the most critical, and the most feared.
I asked the team, “If I wanted to see how a new order is processed, where would I look?”
This led me to a 2,000-line file called process_order.php. This file is the heart of the beast. It has logic for validating stock, talking to a payment gateway (via a cURL request), inserting records into half a dozen database tables, and sending customer emails.
This file is a history book. You can see comments left by developers who haven't worked here in ten years. You can see blocks of code commented out after a business pivot. It's terrifying, but it's also the single most important piece of code in the company. By reading it, I'm not just learning the code; I'm learning the last 15 years of the company's business logic.
Strategy 3: Map the Database
The final piece of the puzzle is the database. The database schema is the Rosetta Stone for a legacy application.
While the PHP code might be a tangled mess of logic, the database schema is the source of truth. It shows the state.
I spent a whole afternoon just looking at the table structure. The naming conventions are inconsistent, and there are almost no foreign key constraints—all relationships are managed “in-application” by the PHP logic. But by looking at the tables, I can see the core entities of the business: users, orders, products, and that one weird table called tbl_tmp_report_data_2011 that everyone is probably too scared to delete.
The Big Realisation: It's a Ship of Theseus
After a week of this archaeological dig, I've realised something crucial. This application wasn't designed this way. It grew this way.
It's a digital Ship of Theseus. It was built incrementally, one urgent feature at a time, by smart people working under deadlines. That “messy” file? It was a clean, 200-line script in 2005. The lack of a framework? They didn't exist in a meaningful way when the project started.
The team knows this. They know the brittle parts better than anyone. They've been the ones patching the holes and keeping it sailing for years. My “fresh eyes” aren't seeing anything they don't already know.
But now, I see it, too. I've built the trust of the team (Part 1) and I've built a mental map of the system (Part 2). I finally have the two things I need to ask the most important question: “What's next?”
The business has new features it wants to build. The team wants to modernise. But you can't just stop the world and rewrite a system that's been running for 20 years. That's a recipe for disaster.
You have to do it piece by piece. You have to build the new around the old, slowly and safely.
Next time, we'll talk about the strategy to do just that.
Part 3: Proposing the Strangler Fig Solution.
Cheers,
Jamie C