Taking the cover off of a legacy PHP web app need not be so painful. I spent the last year traveling around the world, which you can read about on my travel blog. I started my own software engineering consulting firm, digital nomad style and I took work with me. I figured it would be a good idea to keep some flow of income while I was enjoying hiking and beaches and lakes and mountains. I learned a lot of lessons about being a contractor while I was far, far away from anything reminding me of home. Namely, I was pushing out some complicated refactoring work from Malaysia, Fiji and Samoa. Communicating with my clients about their changing requirements became more challenging as the months went on. fI felt more distant from the project with the passing of time and increasing geographical distance. As the technical issues got deeper, I realized I was very glad I had made some fundamental technical decisions at the beginning of my work.
This is when the lessons of my corporate years really paid off. I made sure to set up a well-documented development environment that I could easily spin up and spin down so that I would never run into having to reconfigure my dev env should anything happen to my personal laptop. This multipart series will walk you through my experience inheriting this project. Trigger warning: unflattering screenshots.
My New York-based client handed over access to a shared hosting service with a docroot consisting of:
200+ PHP files, 20 CSS files, 15 JS files, all split among many directories.
a few content-only directories with 1.6GB of content-related data.
access to a Production database.
The PHP code was raw and mostly written in 2009. There was a homemade template framework to spit out HTML files. A teeny, tiny bit of jQuery had been used on the front end. There was no framework, such as Laravel or Eloquent ORM, no distinct service layer or REST APIs, and no test environment. The previous engineer was testing locally and pushing code to Production. It’s never been my style to wing it like that. To get started, I had no choice but to dig in without developer set up instructions, deployment instructions, or, you guessed it, a source control repository.
Let this document be a guide for all of the developers out there who inherit a legacy project and feel overwhelmed by the task-at-hand. Of course I know you, dear reader, are not overwhelmed by this feat, you are merely reading for enjoyment. (I can provide validation for you whenever necessary.) As I walk through the phases of my approach, I will also share my technical philosophy where applicable so you can understand why I took these steps.
Goal
This web app is part social networking app with user profiles, along with messaging, group events and user search. Take this ugly old PHP web app and put a brand new skin on it, provided by a designer. In this phase, we are not adding any new functionality but we also cannot remove any existing functionality, even for the purposes of simplification.
Methodology
How do I start?
For me, divide and conquer has been a computer science strategy that I use in all forms of my life. When it comes to complex technical projects, it has always done me well. I’m comfortable with breaking up large tasks into smaller tasks.
Back in my days working at HBO, when we wanted to modernize older systems, we would go through a “Buy vs. Build” project phase. This was a drawn out process that came with many benefits. It forced us to really think about what it would mean to throw out the entire legacy codebase and rebuild it from scratch using a vendor application. In the case of this project, I had spent quite a few hours documenting all of the existing functionality in a business requirements document.
Beyond the many idiosyncrasies of the app, like configurable widgets on the user dashboard, a quick view of events (in addition to the standard view) and all sorts of combinations of blocking users, profile visibility, and hiding photo galleries, there was also a slew of administrative functionality that allowed the owner of the company to create customized pages in a CMS (with the HTML stored in the database), alter site data, see how users use the site and distribute emails to large mailing lists of users. Each page also has hidden UI components that displayed only when the Admin is logged in that allows him to see extra information and even update user data. My client set a strict goal that we could not remove any existing features!
I knew after all of the hours of digging into these elaborate features that there was no way we could rewrite this thing from scratch and keep track of all of the functionality that would need to be rebuilt. While it would be more painful, we would have to dissect this baby piece by piece. I also did an evaluation on the many out of the box social networking packages. Unfortunately, none of them offer the level of admin tools that he currently has. Re-skinning these packages to meet the designer’s layouts would also potentially break the provided templates. I was leaning towards upgrading the app module by module.
Can we throw the whole thing away?
There is a type of developer out there that exists who only enjoys writing new code; their own code. I was never one of these types of coders. I enjoy learning about how another engineer built a piece of software. I often think that some engineers rush to decisions to throw away old code, because they personally enjoy writing new code, without considering the cost associated with it. Without a defined set of features that need to be rewritten, how can you guarantee a complete rewrite to your client? In our case, the list of requirements was so extensive, my estimate for a complete rewrite was higher than divide-and-conquer refactoring. Also, throwing away code that works is generally not a good idea. Working code is the result of person-hours of labor including countless hours of thought.
In my career, I have never thrown away an entire project’s worth of code for any sort of upgrades including an internal HBO app originally written for Mac Hypercard, rewritten in Java, where we extracted the SQL code. We salvaged something and let me tell ya, these were very complicated SQL queries that some group of people had, years earlier, had spent significant time putting together!
Now you understand why I chose to work with this older codebase. It had not received any lovin’ in a long time. In the next segment, I’ll document the technical steps I took to get started doing technical work on this project. I’d be interested to hear your stories regarding making hard decisions about what to do with older code.