Modernizing Legacy Applications in PHP
()
About this ebook
Related to Modernizing Legacy Applications in PHP
Related ebooks
Mastering Symfony Rating: 0 out of 5 stars0 ratingsBuilding Web APIs with ASP.NET Core Rating: 0 out of 5 stars0 ratingsPHP 5 CMS Framework Development - 2nd Edition Rating: 0 out of 5 stars0 ratingsNode Web Development, Second Edition Rating: 0 out of 5 stars0 ratingsMulti-Tier Application Programming with PHP: Practical Guide for Architects and Programmers Rating: 0 out of 5 stars0 ratingsProfessional PHP Design Patterns Rating: 5 out of 5 stars5/5Programming Problems in Ruby Rating: 0 out of 5 stars0 ratingsUML A Complete Guide - 2020 Edition Rating: 0 out of 5 stars0 ratingsJava 9 with JShell Rating: 0 out of 5 stars0 ratingsDomain-Driven Design in PHP Rating: 0 out of 5 stars0 ratingsSoftware Development Accelerated Essentials: What You Didn't Know, You Needed to Know Rating: 0 out of 5 stars0 ratingsJava for Data Science Rating: 0 out of 5 stars0 ratingsPHP Reactive Programming Rating: 0 out of 5 stars0 ratingsIntegration Testing A Complete Guide - 2020 Edition Rating: 0 out of 5 stars0 ratingsMicrosoft .NET Framework 4.5 Quickstart Cookbook Rating: 0 out of 5 stars0 ratingsAngularJS Complete Self-Assessment Guide Rating: 0 out of 5 stars0 ratingsCloning Internet Applications with Ruby Rating: 5 out of 5 stars5/5AspectJ in Action: Enterprise AOP with Spring Applications Rating: 0 out of 5 stars0 ratingsASP.NET 3.5 CMS Development Rating: 0 out of 5 stars0 ratingsObject-Oriented Design with UML and Java Rating: 4 out of 5 stars4/5Test Driven Development A Complete Guide - 2020 Edition Rating: 0 out of 5 stars0 ratingsCode reuse Complete Self-Assessment Guide Rating: 0 out of 5 stars0 ratingsPHP Error Reporting: How To Do It Right Rating: 0 out of 5 stars0 ratingsDistributed Computing in Java 9 Rating: 0 out of 5 stars0 ratingsJava Web Developer A Complete Guide Rating: 0 out of 5 stars0 ratingsNatural Language Processing with Java Rating: 0 out of 5 stars0 ratingsInstant Hands-on Testing with PHPUnit How-to Rating: 0 out of 5 stars0 ratingsJump Start Web Performance Rating: 0 out of 5 stars0 ratingsSoftware Developer Rating: 0 out of 5 stars0 ratingsPHP and MySQL Web Development All-in-One Desk Reference For Dummies Rating: 0 out of 5 stars0 ratings
Software Development & Engineering For You
Level Up! The Guide to Great Video Game Design Rating: 4 out of 5 stars4/5Adobe Illustrator CC For Dummies Rating: 5 out of 5 stars5/5Python For Dummies Rating: 4 out of 5 stars4/5DevOps For Dummies Rating: 4 out of 5 stars4/5Modern C++ for Absolute Beginners: A Friendly Introduction to C++ Programming Language and C++11 to C++20 Standards Rating: 0 out of 5 stars0 ratingsLearning R Programming Rating: 5 out of 5 stars5/5Grokking Algorithms: An illustrated guide for programmers and other curious people Rating: 4 out of 5 stars4/5Good Code, Bad Code: Think like a software engineer Rating: 5 out of 5 stars5/5Hand Lettering on the iPad with Procreate: Ideas and Lessons for Modern and Vintage Lettering Rating: 4 out of 5 stars4/5How to Write Effective Emails at Work Rating: 4 out of 5 stars4/5Photoshop For Beginners: Learn Adobe Photoshop cs5 Basics With Tutorials Rating: 0 out of 5 stars0 ratingsBeginning Programming For Dummies Rating: 4 out of 5 stars4/5Learn to Code. Get a Job. The Ultimate Guide to Learning and Getting Hired as a Developer. Rating: 5 out of 5 stars5/5Ry's Git Tutorial Rating: 0 out of 5 stars0 ratingsHow Do I Do That in Photoshop?: The Quickest Ways to Do the Things You Want to Do, Right Now! Rating: 4 out of 5 stars4/5How Do I Do That In InDesign? Rating: 5 out of 5 stars5/5Lua Game Development Cookbook Rating: 0 out of 5 stars0 ratingsTiny Python Projects: Learn coding and testing with puzzles and games Rating: 5 out of 5 stars5/5Engineering Management for the Rest of Us Rating: 5 out of 5 stars5/5Data Visualization: a successful design process Rating: 4 out of 5 stars4/5PYTHON: Practical Python Programming For Beginners & Experts With Hands-on Project Rating: 5 out of 5 stars5/5Reversing: Secrets of Reverse Engineering Rating: 4 out of 5 stars4/5iOS App Development For Dummies Rating: 0 out of 5 stars0 ratingsOneNote: The Ultimate Guide on How to Use Microsoft OneNote for Getting Things Done Rating: 1 out of 5 stars1/5Android App Development For Dummies Rating: 0 out of 5 stars0 ratingsLearning Java by Building Android Games Rating: 0 out of 5 stars0 ratings
Reviews for Modernizing Legacy Applications in PHP
0 ratings0 reviews
Book preview
Modernizing Legacy Applications in PHP - Paul M. Jones
Table of Contents
Modernizing Legacy Applications in PHP
Credits
Foreword
About the Author
Acknowledgement
www.PacktPub.com
eBooks, discount offers, and more
Why subscribe?
Preface
1. Legacy Applications
The typical PHP application
File Structure
Page Scripts
Rewrite or Refactor?
The Pros and Cons of Rewriting
Why Don't Rewrites Work?
The Context-switching problem
The Knowledge problem
The Schedule Problem
Iterative Refactoring
Legacy Frameworks
Framework-based Legacy Applications
Refactoring to a Framework
Review and next steps
2. Prerequisites
Revision control
PHP version
Editor/IDE
Style Guide
Test suite
Review and next steps
3. Implement an Autoloader
PSR-0
A Single Location for Classes
Add Autoloader Code
As a Global Function
As a Closure
As a Static or Instance method
Using The __autoload() Function
Autoloader Priority
Common Questions
What If I Already Have An Autoloader?
What are the Performance Implications Of Autoloading?
How Do Class Names Map To File Names?
Review and next steps
4. Consolidate Classes and Functions
Consolidate Class Files
Find a candidate include
Move the class file
Remove the related include calls
Spot check the codebase
Commit, Push, Notify QA
Do ... While
Consolidate functions into class files
Find a candidate include
Convert the function file to a class file
Change function calls to static method calls
Spot check the static method calls
Move the class file
Do ... While
Common Questions
Should we remove the autoloader include call?
How should we pick files for candidate include calls?
What if an include defines more than one class?
What if the one-class-per-file rule is disagreeable?
What if a Class or Function is defined inline?
What if a definition file also executes logic?
What if two classes have the same name?
What about third-party libraries?
What about system-wide libraries?
For functions, can we use instance methods instead of static methods?
Can we automate this process?
Review and next steps
5. Replace global With Dependency Injection
Global Dependencies
The replacement process
Find a global variable
Convert global variables to properties
Spot check the class
Convert global properties to constructor parameters
Convert instantiations to use parameters
Spot check, Commit, Push, Notify QA
Do ... While
Common Questions
What if we find a global in a static method?
Is there an alternative conversion process?
What about class names in variables?
What about superglobals?
What about $GLOBALS?
Review and next steps
6. Replace new with Dependency Injection
Embedded instantiation
The replacement process
Find a new keyword
Extract One-Time creation to dependency injection
Extract repeated creation to factory
Change instantiation calls
Spot Check, Commit, Push, Notify QA
Do ... While
Common Questions
What About Exceptions and SPL Classes?
What about Intermediary Dependencies?
Isn't this a lot of code?
Should a factory create collections?
Can we automate all these Injections?
Review and next steps
7. Write Tests
Fighting test resistance
The way of Testivus
Setting up a test suite
Install PHPUnit
Create a tests/ directory
Pick a class to test
Write a test case
Do ... While
Common Questions
Can we skip this step and do it later?
Come On, Really, Can We Do This Later?
What about hard-to-test classes?
What about our earlier characterization tests?
Should we test private and protected methods?
Can we change a test after we write it?
Do we need to test Third-party libraries?
What about code coverage?
Review and next steps
8. Extract SQL statements to Gateways
Embedded SQL Statements
The extraction process
Search for SQL statements
Move SQL to a Gateway class
Namespace and Class names
Method names
An initial Gateway class method
Defeating SQL Injection
Write a test
Replace the original code
Test, Commit, Push, Notify QA
Do ... While
Common Questions
What about INSERT, UPDATE, and DELETE Statements?
What about Repetitive SQL strings?
What about complex query strings?
What about queries inside non-Gateway classes?
Can we extend from a base Gateway class?
What about multiple queries and complex result structures?
What if there is no Database Class?
Review and next steps
9. Extract Domain Logic to Transactions
Embedded Domain Logic
Domain logic patterns
The Extraction Process
Search for uses of Gateway
Discover and Extract Relevant Domain Logic
Example Extraction
Spot check the remaining original code
Write tests for the extracted transactions
Spot check again, Commit, Push, Notify QA
Do ... While
Common Questions
Are we talking about SQL transactions?
What about repeated Domain Logic?
Are printing and echoing part of Domain Logic?
Can a transaction be a class instead of a Method?
What about Domain Logic in Gateway classes?
What about Domain logic embedded in Non-Domain classes?
Review and next steps
10. Extract Presentation Logic to View Files
Embedded presentation logic
The Extraction process
Search for Embedded presentation logic
Rearrange the Page script and Spot Check
Extract Presentation to View file and Spot Check
Create a views/ Directory
Pick a View File name
Move Presentation Block to View file
Add Proper Escaping
Write View File Tests
The tests/views/ directory
Writing a View File Test
Asserting Correctness Of Content
Commit, Push, Notify QA
Do ... While
Common Questions
What about Headers and Cookies?
What if we already have a Template system?
What about Streaming Content?
What if we have lots of Presentation variables?
What about class methods that generate output?
What about Business Logic Mixed into the presentation?
What if a page contains only presentation logic?
Review and next steps
11. Extract Action Logic to Controllers
Embedded action logic
The Extraction Process
Search for Embedded Action Logic
Rearrange the Page Script and Spot Check
Identify Code Blocks
Move Code to Its Related Block
Spot Check the Rearranged Code
Extract a Controller Class
Pick a Class Name
Create a Skeleton Class File
Move the Action Logic and Spot Check
Convert Controller to Dependency Injection and Spot Check
Write a Controller Test
Commit, Push, Notify QA
Do ... While
Common Questions
Can we pass parameters to the Controller method?
Can a Controller have Multiple actions?
What If the Controller contains include Calls?
Review and next steps
12. Replace Includes in Classes
Embedded include Calls
The Replacement process
Search for include Calls
Replacing a Single include Call
Replacing Multiple include Calls
Copy include file to Class Method
Replace the original include Call
Discover coupled variables through testing
Replace other include Calls and Test
Delete the include file and test
Write a test and refactor
Convert to Dependency Injection and test
Commit, Push, Notify QA
Do ... While
Common QuestionsCan one class receive logic from many include files?
What about include calls originating in non-class files?
Review and next steps
13. Separate Public and Non-Public Resources
Intermingled resources
The separation process
Coordinate with operations personnel
Create a document root directory
Reconfigure the server
Move public resources
Commit, push, coordinate
Common Questions
Is This Really Necessary?
Review and next steps
14. Decouple URL Paths from File Paths
Coupled Paths
The Decoupling Process
Coordinate with Operations
Add a Front Controller
Create a pages/ Directory
Reconfigure the Server
Spot check
Move Page scripts
Commit, Push, Coordinate
Common Questions
Did we really Decouple the Paths?
Review and next steps
15. Remove Repeated Logic in Page Scripts
Repeated logic
The Removal Process
Modify the Front controller
Remove Logic from Page Scripts
Spot Check, Commit, Push, Notify QA
Common Questions
What if the Setup Work Is Inconsistent?
What if we used inconsistent naming?
Review and next steps
16. Add a Dependency Injection Container
What is a Dependency Injection Container?
Adding a DI Container
Add a DI Container Include File
Add a Router Service
Modify the Front Controller
Extract Page Scripts to Services
Create a Container Service
Route the URL Path to the Container Service
Spot Check and Commit
Do ... While
Remove pages/, Commit, Push, Notify QA
Common Questions
How can we refine our service definitions?
What if there are includes In the Page Script?
Can we reduce the size of the services.php file?
Can we reduce the size of the router service?
What if we cannot update to PHP 5.3?
Review and next steps
17. Conclusion
Opportunities for improvement
Conversion to Framework
Review and next steps
A. Typical Legacy Page Script
B. Code before Gateways
C. Code after Gateways
D. Code after Transaction Scripts
E. Code before Collecting Presentation Logic
F. Code after Collecting Presentation Logic
G. Code after Response View File
H. Code after Controller Rearrangement
I. Code after Controller Extraction
J. Code after Controller Dependency Injection
Index
Modernizing Legacy Applications in PHP
Modernizing Legacy Applications in PHP
Copyright © 2016 Paul M. Jones
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
First published: August 2016
Production reference: 1260816
Published by Packt Publishing Ltd.
Livery Place
35 Livery Street
Birmingham B3 2PB, UK.
ISBN 978-1-78712-470-7
www.packtpub.com
Credits
Author
Paul M. Jones
Acquisition Editor
Frank Pohlmann
Technical Editor
Danish Shaikh
Indexer
Mariammal Chettiyar
Graphics
Disha Haria
Production Coordinator
Arvindkumar Gupta
Cover Work
Arvindkumar Gupta
Foreword
In early 2012, while attending a popular PHP conference in Chicago, I approached a good friend, Paul Jones, with questions about PSR-0 and autoloading. We immediately broke out my laptop to view an attempt at applying the convention and Paul really helped me put the pieces together in short order. His willingness to jump right in and help others always inspires me, and has gained my respect.
So in August of 2012 I heard of a video containing a talk given by Paul at the Nashville PHP User Group, and was drawn in. The talk, It Was Like That When I Got Here: Steps Toward Modernizing A Legacy Codebase, sounded interesting because it highlighted something I am passionate about: refactoring.
After watching I was electrified! I often speak about refactoring and receive inquiries on how to apply it for legacy code rather than performing a rewrite. Put another way, how is refactoring possible in a codebase where includes and requires are the norm, namespaces don't exist, globals are used heavily, and object instantiation runs rampant with no dependency injection? And what if the codebase is procedural?
Paul's focus of modernizing a legacy application filled the gap by getting legacy code to a point where standard refactoring is possible. His step-by-step approach makes it easier for developers to get the bear dancing so continued improving of code through refactoring can happen.
I felt the topic was a must see for PHP developers and quickly fired off an email asking if he'd be interested in flying to Miami and giving the same talk for the South Florida PHP User Group. Within minutes my email was answered and Paul even offered to drive down from Nashville for the talk. However, since I started organizing the annual SunshinePHP Developer Conference to be held February in Miami we decided to have Paul speak at the conference rather than come down earlier.
Fast forward two years later, and here we are in mid-2014. Developing with PHP has really matured in recent years, but it's no secret that PHP's low level of entry for beginners helped create some nasty codebases. Companies who built applications in the dark times simply can't afford to put things on hold and rebuild a legacy application, especially with today's fast paced economy and higher developer salaries. To stay competitive, companies must continually push developers for new features and to increase application stability. This creates a hostile environment for developers working with a poorly written legacy application. Modernizing a legacy application is a necessity, and must happen. Yet knowing how to create clean code and comprehending how to modernize a legacy application are two entirely different things.
Paul and I have been speaking to packed rooms at conferences around the world about modernizing and refactoring. Developers are hungry for knowledge on how to improve the quality of their code and perfect their craft. Unfortunately, we can only reach a small portion of PHP developers using these methods. The time has come for us to create books in hopes of reaching more PHP developers to improve the situation.
I see more and more developers embrace refactoring into their development workflow to leverage methods outlined in my talks and forthcoming book Refactoring 101. But understanding how to use these refactoring processes on a legacy codebase is not straight forward, and sometimes impossible. The book you're about to read bridges the gap, allowing developers to modernize a codebase so refactoring can be applied for continued enhancement. Many thanks to Paul for putting this together. Enjoy!
Adam Culp
(https://leanpub.com/refactoring101)
About the Author
Paul M. Jones is an internationally recognized PHP expert who has worked as everything from junior developer to VP of Engineering in all kinds of organizations (corporate, military, non-profit, educational, medical, and others). He blogs professionally at www.paul-m-jones.com and is a regular speaker at various PHP conferences.
Paul's latest open-source project is Aura for PHP. Previously, he was the architect behind the Solar Framework, and was the creator of the Savant template system. He was a founding contributor to the Zend Framework (the DB, DB_Table, and View components), and has written a series of authoritative benchmarks on dynamic framework performance.
Paul was one of the first elected members of the PEAR project. He is a voting member of the PHP Framework Interoperability Group, where he shepherded the PSR-1 Coding Standard and PSR-2 Coding Style recommendations, and was the primary author on the PSR-4 Autoloader recommendation. He was also a member of the Zend PHP 5.3 Certification education advisory board.
In a previous career, Paul was an operations intelligence specialist for the US Air Force. In his spare time, he enjoys putting .308 holes in targets at 400 yards.
Acknowledgement
Many thanks to all of the conference attendees who heard my It Was Like That When I Got Here presentation and who encouraged me to expand it into a full book. Without you, I would not have considered writing this at all.
Thank you to Adam Culp, who provided a thorough review of the work-in-progress, and for his concentration on refactoring approaches. Thanks also to Chris Hartjes, who went over the chapter on unit testing in depth and gave it his blessing. Many thanks to Luis Cordova, who acted as a work-in-progress editor and who corrected my many pronoun issues.
Finally, thanks to everyone who bought a copy of the book before it was complete, and especially to those who provided feedback and insightful questions regarding it. These include Hari KT (a long-time colleague on the Aura project), Ron Emaus, Gareth Evans, Jason Fuller, David Hurley, Stephen Lawrence, Elizabeth Tucker
Long, Chris Smith, and others too numerous to name. Your early support helped to assure me that writing the book was worthwhile.
www.PacktPub.com
eBooks, discount offers, and more
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.
https://www2.packtpub.com/books/subscription/packtlib
Do you need instant solutions to your IT questions? PacktLib is Packt's online digital book library. Here, you can search, access, and read Packt's entire library of books.
Why subscribe?
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Preface
I have been programming professionally in one capacity or another for over 30 years. I continue to find it a challenging and rewarding career. I still learn new lessons about my profession every day, as I think is the case for every programmer dedicated to this craft.
Even more challenging and rewarding is helping other programmers to learn what I have learned. I have worked with PHP for 15 years now, in many different kinds of organizations and in every capacity from junior developer to VP of Engineering. In that time, I have learned a lot about the commonalities in legacy PHP applications. This book is distilled from my notes and memories from modernizing those codebases. I hope it can serve as a path for other programmers to follow, leading them out of a morass of bad code and bad work situations, and into a better life for themselves.
This book also serves as penance for all of the legacy code I have left behind for others to deal with. All I can say is that I didn't know then what I know now. In part, I offer this book as atonement for the coding sins of my past. I hope it can help you to avoid my previous mistakes.
Chapter 1. Legacy Applications
In its simplest definition, a legacy application is any application that you, as a developer, inherit from someone else. It was written before you arrived, and you had little or no decision-making authority in how it was built.
However, there is a lot more weight to the word legacy among developers. It carries with it connotations of poorly organized, difficult to maintain and improve, hard to understand, untested or untestable, and a series of similar negatives. The application works as a product in that it provides revenue, but as a program, it is brittle and sensitive to change.
Because this is a book specifically about PHP-based legacy applications, I am going to offer some PHP-specific characteristics that I have seen in the field. For our purposes, a legacy application in PHP is one that matches two or more of the following descriptions:
It uses page scripts placed directly in the document root of the web server.
It has special index files in some directories to prevent access to those directories.
It has special logic at the top of some files to die() or exit() if a certain value is not set.
Its architecture is include-oriented instead of class-oriented or object-oriented.
It has relatively few classes.
Any class structure that exists is disorganized, disjointed, and otherwise inconsistent.
It relies more heavily on functions than on class methods.
Its page scripts, classes, and functions combine the concerns of model, view, and controller into the same scope.
It shows evidence of one or more incomplete attempts at a rewrite, sometimes as a failed framework integration.
It has no automated test suite for the developers to run.
These characteristics are probably familiar to anyone who has had to deal with a very old PHP application. They describe what I call a typical PHP application.
The typical PHP application
Most PHP developers are not formally trained as programmers, or are almost entirely self-taught. They often come to the language from other, usually non-technical, professions. Somehow or another, they are tasked with the duty of creating webpages because they are seen as the most technically-savvy person in their organization. Since PHP is such a forgiving language and grants a lot of power without a lot of discipline, it is very easy to produce working web pages and even applications without a lot of training.
These and other factors strongly influence the underlying foundation