I would imagine that at one time or another, every PHP developer comes to the fork in the road that I have just hit. Last summer, I started working on a large enterprise application for my company, and the initial approach was, at that time, a pretty typical one for me. I went to my standard code library, developed on my own over a period of 3 or 4 years and starting piecing together a core application that I could start building on. I worked on this application diligently from June to September, and I would say in that time I had made it 70% of the way through the app. I was being relatively careful about doing manual functional tests, and I felt good about what I was doing with the application where security practices were concerned. Then 2 things happened almost simultaneously that really put a wrench in the works.
First, I really started to take more of an interest in the PHP community, attending an event, starting this blog, and even writing for PHP Architect magazine. This really served to broaden my awareness of what was going on in the PHP community at large, and what topics are “trending”, so to speak. I tried, and still continue to try, to absorb as much as I can, and I enjoy the fact that I can learn something new every day.
Second, we had a series of events at work that demanded my undivided attention. Nothing catastrophic or even bad for that matter, but important enough that I needed to prioritize what I was doing and unfortunately, my big app had to be shelved for a while. I think the last commit to the repo was in October of last year, which troubles me because strategically, getting this project deployed is very important to the business.
Now things are calming down, in as much as they can, and I am finally able to put this application back on my priority list. I am both happy, and completely stuck as to what to do. In the last 6 months, I have immersed myself in PHP, new frameworks, newer features, unit testing, and all of the other things that the PHP community is evangelizing about these days. Then I looked at my code, ugh. It’s not that the code is particularly bad, it is just that now I know it could be done so much better. Now what? Do I just keep going and get the last 30% or so of this thing done? Do I start refactoring it to merge in a few key concepts? Or do I just blow it up and start over using everything that I have learned in the last 6 months?
The easiest thing to do is just “keep calm and carry on”. I am not terribly far from the finish line, and there is a case to be made that says I need to get this thing done and just put the project behind me (although let’s face it, these projects are rarely ever really behind you). Again, the code is not awful, the flow of it is solid, and the fact that I feel like I know more today doesn’t necessarily mean anything that has already been done was bad, it just wasn’t as good as it could be.
This is the middle of the road solution. Resurvey the the code and look for some obvious things that would benefit from a refactoring exercise(s). To be fair, I have done been through a few refactoring exercises on this app already:
- Introduction of namespaces: didn’t really need it for this project, but to facilitate future expansion, it wasn’t such a difficult refactor that I thought it wouldn’t add value at some point.
- PSR1/2 conventions: This one just made sense to let Codesniffer beat me up and make me clean the code up perfectly
- A new feature to streamline filtering input and escaping output
Refactoring an application is an essential part of the lifecycle of any application, and in my view, we should never take a “one and done” approach to any substantive project. There are always things we can improve, and we should when it is prudent.
Maybe I just need to start over. Put the project on a cutting edge framework, use test driven development, and go back to square one. I started think about this after re-reading a blog post by Phil Sturgeon that pointed out some limitations that CodeIgniter would not be able to overcome without a total rewrite. This would certainly provide the best gateway to future-proofing the application and making it as robust as humanly possible.
The geek in me really wants to blow this thing up, go back to square one and “do it right” based on what I know today. I would change the database from SQL Server to MySQL, move the production environment from Windows to Linux, and really just completely start over. In truth, this is a little grandiose, almost to the point of being indifferent to the concept of delivering business value. There is no question that it would deliver a more robust application, but it would not have a substantial effect, positive or negative, on the user.
On the other hand, the idea of just rolling on through and finishing it the way I started would probably get me to deployment relatively quick, and believe me, that is appealing at this point. Let’s face it, no one is going to be reviewing this code, and even if they were, I feel like everything I have done to this point is totally defensible. The code works, and I have confidence that the deployment would be a success with no more headaches than any other project of this magnitude.
Making the Decision
The whole reason I am writing this post, other than to just get my thoughts down and help make the call, is to illustrate the importance of remembering that as developers, one of our key objectives for the client is to deliver value. This is a fact that can sometimes get away from us. Remember that our customers typically do not care what framework something is on, or what database we are using. What they care about is that the end product delivers value to the business. As much as it pains me, it is clear, blowing it up and starting over is not an option. Yes, I can do things in 1 hour on a framework that take 2 hours when you are rolling your own, but the reality is that the 2 hours has already been spent and the resulting code is already there. It’s not faster to re-develop when the work has already been done.
In the end, the decision is pretty easy, blowing it up is impractical and I do not believe in leaving something as-is with the idea that it can never be incrementally improved. So it is simple, I will refactor. But how much time should I spend refactoring? And what should be prioritized for refactoring? As I was roughing out the idea for this post, the answer to the first question was handed to me. I got an email from work that a new initiative was brewing, and that it was very likely I was going to spearhead it. That pretty much sewed it up, I am not going to have a world of time on my hands to refactor, so whatever I do needs to count for something.
In the end, I have decided to give myself two days to do a code review and one week to refactor. In two days, I will have to choose what is going to be refactored before development resumes, and those tasks will have to be able to be completed within 7 days. So how do I prioritize?
- Will there be a benefit to the user?
- Does the task directly add value for the company?
- Will the refactor task improve my chances for successful deployment?
- Will the refactor task make future maintenance easier?
These are just some of the questions I will be asking myself. I am sure other questions will arise during the code review, but at the end of it, the goal remains the same: deliver a product in a timely fashion that adds business value. As developers, we cannot ignore the need to deliver value. Likewise we cannot ignore the notion of something that makes the code “latest and greatest” but doesn’t do anything to improve the app in the user’s eyes. We have to be willing to wait and use the latest and greatest on the next project. If we don’t remain cognizant of this we run the risk of blowing up a project so many times that it never gets delivered.