I’ve read dozens of technical books and almost all of them suffer from the same problem: lack of real-world examples and a feeling that if you apply every concept and technique described in them you will end up with a perfect piece of software. Today, I am happy to say that “Modernizing Legacy Applications in PHP” is a rare exception to this.
Developers often think that the best way to fix legacy applications is by simply rewriting it from scratch. Paul Jones thinks differently, and right at the beginning of the book he hits developers where it hurts by giving a couple of examples of famous failed attempts of complete software rewrites. Next, he talks briefly about the reasons most of such rewrite attempts fail and why refactoring is usually the best approach to modernize a legacy application. Having worked with lots of legacy applications myself, this really resonates with me. For many times I felt that throwing the old code out of the window was the only solution, and the points on the book made me understand some of the reasons why the software became like that and made me realize that most of them are non-technical and will affect a rewrite as well.
After destroying the dreams of most of the developers and arguing that refactoring is the best approach, the author guides the reader through the refactoring of a legacy PHP application. One made of dozens of includes and PHP pages, full of HTML, SQL and PHP procedural code all mixed up. A true definition of spaghetti code that I’m sure every developer has seen at least once.
As the author goes about the refactoring process, you won’t really see anything that you’ve never seen in books like “Refactoring” and “Patterns of Enterprise Application Architecture”. What really makes the book shine is the baby-steps approach in applying the ideas in these books to a sample application that is very similar to a real one. It starts by introducing the autoloading concept and how to add one to the application, as this will be the foundation for everything else in the book. With that in place, he then goes on slowly extracting pieces of code to separate classes. First, groups similar functions into classes. Quickly, but still in small steps, SQL queries go into Gateways classes, then domain logic into Transactions; presentation logic into View classes; page logic into controllers; and, finally when almost all the code was split into separate classes, a dependency injection container is introduced to glue all the pieces together.
It is interesting to note that, as it is expected of a refactoring, during the entire process the application never ceased to work. In fact, after each step, the author reminds us of the importance of coordinating with QA and notifying them about the underlying changes in the application so as to guarantee that the application still works as expected.
During the entire book, Paul is very pragmatic and down-to-earth about the process. He often tries to make it clear that the whole point is not about making the application perfect, but to make it better after each step of the way as so as to pavement the way for future improvements. At the end of the book, there is a list of many possible improvements that are still possible to implement, but it is important to remember that all of them are only now possible because of the refactoring that was made to modernize the codebase up to this point.
In my experience as a developer, I feel like that perfect code is something most people never achieve. Your knowledge about the problems you’re trying to solve and the tools you use to solve them is often limited and this limit you determinate how good your solution will be. As your knowledge grows, the quality of the solutions should grow as well and constant refactoring is the way you can guarantee that this will be applied to the entire codebase. This book was a good reminder of that.