Chapter 14. Software Engineering Practices You Should Be Aware Of

Unlike previous chapters, this chapter is not a detailed look at how to do something in a PHP program. Instead, it looks at a few tools and topics that apply to software development in general. These techniques are especially useful when coordinating with other people but can also be valuable when you’re working on a project all by yourself.

The PHP code you write to make the computer do something specific isn’t the entirety of your software project. You also need to keep track of how your code has changed so you can go back to an earlier version if a bug creeps in or reconcile changes that two people have made to the same parts of the code. If bugs do come up or users make requests for new features, how do you keep track of those tasks? Has a bug been fixed? What code was changed to fix that bug? Who fixed it? Is the version of the code with the bug fix live for users to see yet? Source control systems (discussed in “Source Control”) and issue tracking systems (discussed in “Issue Tracking”) give you the information you need to answer these questions.

On all but the smallest projects, when you make changes, you don’t want to edit the code that is running on the actual website that users interact with. Doing that exposes potential problems to your users. Your users will not be happy if you accidentally save a file with a typo in it, or you make a change that bogs down your server with time-consuming calculations.

Instead, work on a set of files that gets released to the servers that users interact with only when you’re happy with how the program works. “Environments and Deployment” discusses how to do this and how to make your PHP programs run smoothly in different contexts.

The chapter concludes with “Scaling Eventually”, a brief discussion of when to worry about your website’s performance and how to optimize it when necessary.

Source Control

A source control system keeps track of changes to your files. It lets you review the history of how your code has changed, see who made what changes, and compare versions. With a source control system, two developers can work independently on changes and then combine them with ease.

A source control system is essential when more than one person is working on a project, but it is also useful for projects that you’re working on alone. Being able to “go back in time” and see what your code contained at a previous point is a lifesaver when you’re trying to figure out when a bug was introduced.

There are many popular source control systems, and which one you use will either be a matter of personal preference (for your own projects) or a foregone conclusion (when you’re working on an existing project that already has one). The code for the PHP engine itself is managed using the Git source control system. You can browse the PHP engine’s source code at http://git.php.net. Other popular source control systems include Mercurial and Subversion.

Source control systems excel at handling text files. Since your PHP code is essentially a collection of text files, there’s nothing special you need to do to make it play nicely with any popular source control system. Still, following some conventions will make your code easier to manage.

One convention is how to organize classes in files. If you’re writing object-oriented code, define only one class per file and make the filename the same as the class name (plus the .php extension). If you define classes inside namespaces, make a directory that corresponds to each namespace component, and arrange your files under those directories.

For example, a class named CheeseGrater goes in the file CheeseGrater.php. If you’ve defined that class in a Utensils namespace, then CheeseGrater.php goes in a Utensils subdirectory. Multiple levels of namespace mean multiple subdirectories. A class whose fully qualified name is \Kitchen\Utensils\CheeseGrater goes in the path Kitchen/Utensils/CheeseGrater.php.

This convention is known as PSR-4. PSR means PHP Standard Recommendation. The PHP Standard Recommendations are conventions on coding style and organization that most major PHP projects use.

Issue Tracking

Methods abound for keeping track of what you should be working on. Formal issue tracking systems are a reliable way to keep lists of bugs, feature requests, and other work that needs to be done. These systems ensure that each task is assigned to a person responsible for it. Each task is associated with relevant metadata, such as priority, estimated length of time to do it, progress and completion status, and comments. This metadata makes it a breeze to sort, search, and understand the background of each issue.

There are lots of issue tracking systems out there, and, like with source control systems, which one you use may be dictated by whatever’s already in use in the project you’re joining or the company you work for. If you’re looking for a free system to try out, one worth mentioning is MantisBT, because it is open source and itself written in PHP.

Issue tracking systems are agnostic about what programming language you’re using, so no special work is required to get your PHP programs to play nicely with them. A helpful convention, though, is to refer to issue IDs liberally in your program when you’re writing code relevant to a particular issue.

Each issue tracked by the system gets an ID. It might be numbers, letters, or a combination, and it provides a short and unique way to reference an issue. For example, imagine a bug with the description “Login doesn’t work when there’s a + in email address” that, when entered into the system, gets assigned the ID MXH-26. When you write the code to fix the problem, reference that issue ID in a comment. For example:

// MXH-26: URL-encode email address to prevent problems with +
$email = urlencode($email);

This way, when another developer is looking at the code, she can see the issue number and look it up in the issue tracking system for context and an explanation of why your code is there.

Environments and Deployment

Ideally, the files you’re editing when you’re writing your PHP program are not the same files your web server is reading when it is responding to user requests. Editing those “live” files directly can cause many problems:

  • Your users will immediately see errors if you save a file with a typo.
  • Bad guys may be able to access backup copies that your editor saves automatically.
  • You don’t have a good way to test changes before real users see them.

Avoid these problems by maintaining different environments—separate contexts where your code can run. At a minimum, you need a development environment and a production environment. The development environment is where you do your work and the production environment is where you run the code that real users interact with. A typical setup is that the development environment is on your own computer and the production environment is on a server in a data center or cloud hosting provider such as Amazon Web Services or Google Cloud Platform.

Like the other aspects of software engineering discussed in this chapter, there are many ways of setting up different environments, moving code between environments, and managing all the different computers involved. These tools and techniques are typically not language-specific. There are things you can do in your PHP code, however, to make it easier to run seamlessly in different environments.

The most important thing is to separate environment-specific configuration information from your code so the configuration can be swapped without changing the code itself. This information includes data such as database hostnames and login credentials, locations of log files, other filesystem paths, and verbosity of logging. Once this information is in a separate file, PHP gives you a few methods for getting it into your program.

The parse_ini_file() function turns the contents of a key=value config file (the same format that the PHP engine’s php.ini file uses) into an associative array. For example, consider the following configuration file:

;
; Comment lines in a config file start with semicolon
;

; Database Information
; Need quotes around the dsn value because of the = inside it
dsn="mysql:host=db.dev.example.com;dbname=devsnacks"
dbuser=devuser
dbpassword=raisins

Example 14-1 reads that configuration file (assuming it’s been saved into config.ini) and uses the configuration data to establish a database connection.

Example 14-1. Reading a configuration file
$config = parse_ini_file('config.ini');
$db = new PDO($config['dsn'], $config['dbuser'], $config['dbpassword']);

In Example 14-1, the array returned by parse_ini_file() contains keys and values that correspond to each key=value line in config.ini. In a different environment with different database connection information, nothing has to change in the PHP program. The only thing necessary to establish the right connection is a new config.ini file.

Scaling Eventually

If you spend time around software engineers or businesspeople interested in building or running big systems, you’ll hear them ask questions like “Does this scale?” or “Is this system scalable?” They are not talking about cleaning fish. They are wondering, sometimes imprecisely, what happens when this system gets big and busy? Does the website that is speedy with 3 people using it get slow when 3,000 people are using it? What about 3,000,000 people?

The best advice about making a scalable system for a beginning programmer is “don’t worry about it for now.” It is far more important to get things (mostly) working at first with just a light burden on your application than it is to ensure up front that everything will be OK with a heavy burden.

What’s more, when you do start to notice performance issues in your application, your PHP code is probably not the biggest problem. Many things can affect an application’s performance. An inefficient database query that takes a few seconds to run makes a web page load very slowly, even if the PHP program sending the query to the database and generating HTML from the database’s response only takes a few milliseconds to do its part. A web page that the server quickly sends to a client still feels slow to a human user if the HTML loads hundreds of images that take a long time to display in a web browser.

When you do get to the point of ensuring that the PHP-specific parts of your application are speedy, use a profiler to gather data on how the PHP engine performs when running your code. The two most popular open source profilers are Xdebug and XHProf. XHProf has not been updated to work with PHP 7. Xdebug supports PHP 7 as of its 2.4.0rc1 release in November 2015.

As discussed in Chapter 12, Xdebug integrates with several IDEs, including PhpStorm and NetBeans. To learn about profiling in PhpStorm, read the JetBrains article about it. If you’re not using PhpStorm, check out the Xdebug docs for generic information on getting Xdebug’s profiler up and running and then viewing the profiling output.

Chapter Summary

This chapter covered:

  • Understanding what a source control system is
  • Organizing classes into files with the PSR-4 convention
  • Using an issue tracking system
  • Referencing issue IDs in code comments
  • Working in separate environments for development and production
  • Putting environment-specific information in a configuration file
  • Reading a configuration file with parse_ini_file()
  • Being comfortable with not worrying about scalability at first
  • Learning where to find more information on using the Xdebug and XHProf profilers