When I think of best practices in WordPress development, I think of the hundreds of WordPress tutorials I’ve read and I realize there is a common pattern. In most cases, the focus is on the specifics of writing code. While code is at the core of what we do as developers, sometimes we don’t see the forest for the trees. So take a step back with me and let’s go beyond just writing better code and take a look at how we can better structure, manage, test, document and deploy our code.
Best practices for site builders
A site builder is someone who builds WordPress sites professionally and, while they are often viewed as a web developer by their clients, in reality they aren’t coders. They really shine when it comes to finding the right WordPress theme or plugin, or combination thereof, to meet a client’s needs. Typically, they also know enough about code to be dangerous. If this describes you, I want to take a moment to encourage you to keep learning more about coding. However, I’d also like to share a few best practices that I think you should take to heart:
- * Do your research — Just because a plugin or theme meets a client’s need, doesn’t always mean it is the right tool for the job. Don’t evaluate a theme only on what it looks like or a plugin based solely on what it can do. Be sure to do a 360° evaluation. At a minimum, take a look at its ratings, reviews, support history, and the date it was last updated. These, along with many other indicators, can help you make the best choice. Also, if a free plugin isn’t in the WordPress repository, there is usually a good reason. Don’t just download any old free theme or plugin you find on Google because these typically haven’t undergone any kind of code review and can often contain malicious code.
- * If you didn’t make it, don’t edit it! — When you first start learning about code, you realize that you have the power to change things. As Uncle Ben said, “With great power comes great responsibility”. Please realize that directly editing a plugin or theme, or WordPress core for that matter, is a bad idea. The next time that you click the ‘Update’ button, all of your changes will be lost. Sure, you can reapply your changes after each update, but there is a better way…
- * Learn to create child themes — If you ever need to customize a theme, child theming is the way to go. When you create your own theme, only you will be handling updates so you won’t have to worry about losing your changes. Because it is a child theme, it inherits the templates, styling and functionality from the parent. If you want to make changes, all you need to do is override the things you want to change. If all you want to change is styling and you aren’t sure how to create a child theme, then you can use tools like the Simple Custom CSS plugin or the Custom CSS module in JetPack.
- * Learn to create site-specific plugins — Site-specific plugins are useful when you want to make a change on your site that should persist if you were to ever switch themes. They are also useful when you want to edit or extend an existing plugin. So next time, rather than just dropping code in your theme’s
functions.phpfile, create a site specific plugin… your future self will thank you!
Best practices for coders
2.1 Writing Code
Typically, when talking about the best practices for writing code, this is where we would jump into the details. But, let’s take a second to discuss some of the higher level concepts that have influenced those details.
- * Readability — Did you know that the average developer spends more of their time reading code than actually writing it? What this means is that taking a little extra time to write readable code could potentially save yourself and other developers a significant amount of time. Who wouldn’t want to take the most time consuming task in their day and make it easier? Apparently, a lot of people do because we have things like the WordPress Coding Standards. Six months down the road when you have to debug your own code, you’ll be glad you made it easy on the eyes.
- * Reliability — It should be obvious, but when you write code it should be able to do the same thing over and over again without fail. However, this isn’t always the case. Working code can fail for lots of reasons, such as failing to check for unexpected data types, or running it on a server that is configured differently. Because of this, it is important that we utilize the battle-tested WordPress APIs as much as possible. I’m sure you write amazing code, but your code hasn’t been shipped out to millions of users and tested on an ungodly number of different server configurations.
- Along these same lines, make sure you prefix your function names, class names, post types, taxonomy names, etc. This will prevent potential naming conflicts with other plugins and/or themes.
- * Reusability — Copying and pasting code snippets isn’t the way you should reuse code. What happens when you need to make a small change to something you copied to 10 different places in the code? Yes, you will have to hunt them down and hope you didn’t miss any. This is exactly why principles like Don’t Repeat Yourself exist. If you find yourself doing the same things over and over, abstract the code. On a higher level, reusability could mean packaging code into a separate plugin. If you need the same functionality across multiple sites, creating a plugin will allow you share and easily maintain that code.
- * Flexibility — Flexibility is defined as “the quality of bending easily without breaking.” I’d have to say that the true beauty of WordPress is its flexibility. You can select a handful of plugins and easily bend WordPress to meet your needs without breaking your site. Of course, sometimes things do break, but that is usually because we as developers aren’t following best practices. Take, for example, a theme that includes its own version of jQuery on the front end of the site. It may not seem like a big deal to the theme developer because everything works fine when he or she tests it. However, when a user installs a plugin that is expecting the version of jQuery that ships with WordPress core, things will not work as expected. In order to provide flexibility to its users, WordPress provides some strict rules regarding things like enqueueing scripts and stylesheets and we are all the better for abiding by them.
- * Extensibility — When writing code, it is important to take into account future growth. WordPress did a great job of this when implementing actions and filters. I would dare say that it is WordPress’s extensibility that makes it such a widely adopted platform today. When creating a theme or plugin, be sure to think ahead and add a few strategically placed action and filter hooks of your own. This will encourage others to use what you’ve created and build on top of it.
2.2 Structuring code
Beyond just writing code, there is also a higher level design or architecture that must be considered. This is an entire field of study, so consider this a very brief introduction. I encourage you to go do your own research and learn more about it.
- * File Structure — Thinking about your file structure and what belongs in a file early on can greatly simplify code maintenance later. The ultimate goal here is to have files that handle distinct sets of functionality and that are clearly named. As a general rule, a single file should contain a single PHP class. For example, if I have a PHP class that handles a Google Maps API integration, then the file might be named something like
google-maps-api.php. I may also drop that into a folder labeled ‘integrations’ for additional context. It is a simple thing, but the more descriptive and organized your file structure is, the easier it will be for you and other developers to to get an overall picture of the code base.
- * Separation of Concerns — Unfortunately, the average WordPress developer has a tendency to utilize PHP classes as name-spaced containers for code rather than for their intended purpose. As a result, it isn’t uncommon to see a plugin with a single god-object. In most cases, these large classes should be broken down into several smaller classes, each of which serve a specific purpose. For example, if your plugin has an admin page, then you should probably have a special class that just handles the display of that page. As per the previous section, we would probably want to call the file something like
settings-page.phpand place it in an ‘admin’ folder in our plugin. This separation of concerns makes it easier to maintain the code and can help reduce bugs.
- * Design Patterns — I would venture to say that most WordPress developers learn PHP as they go and don’t start with a solid knowledge of PHP or a background in computer science. Because of this, many WordPress developers aren’t aware of software design patterns that may be obvious to other, more experienced developers. There is a wealth of resources out there, and just Googling for the term ‘PHP Design Patterns’ can go a long way. There is a great book titled Professional PHP Design Patterns that I would recommend as a place to get started. If actual code examples are more your thing, then there is also a great pattern library you can browse through. The Singleton Pattern is probably one of the more common design patterns used in WordPress plugins. I would also recommend researching the SOLID principles of object oriented programming and the MVC pattern.
2.3 Managing code
If we are going to write reusable code, it is important that we manage the code in a way that makes that easy.
2.3.1 Version control
First and foremost, you should be using version control. In a nutshell, version control allows you to track changes that were made to files in a project. You can restore a project to a specific state, tag versions, and much more. Git is the most popular version control system, although Subversion is used to manage the WordPress codebase and the themes and plugins in the WordPress repository. The primary benefit of version control is that you won’t lose code, but it also allows you to collaborate with others and manage different versions of your code.
While version control is ideal for working with teams, it can be extremely useful even if you are the only one who touches the code. For example, being able to correlate the date a problem occurred with code changes that happened around that timeframe can be a tremendous help in getting to the bottom of an issue. It is also great to be able to restore the code when someone accidentally deletes a file or a site gets hacked.
Be sure that you don’t just store the code in a repository on your machine. Use a service like GitHub or BitBucket to host your repositories in the cloud. This way when other team members need to access the code, it is simply a URL away. GitHub provides unlimited public repositories and has a more active developer community. It is a great place for publicizing open source projects and getting feedback and involvement from other developers. BitBucket provides unlimited private repositories and is perfect for hosting private client sites.
2.3.2 Dependency management
Once all of your code is in version control, it is time to start using a dependency manager. A common scenario is that you are creating a WordPress website and this site has a custom theme and a handful of plugins. At any given time, the site might be running different versions of each of these plugins as well as a specific version of WordPress. Let’s say you go and update all of the plugins and then update WordPress. Now let’s assume that something broke. Can you roll your site back to its original state before the update? Do you remember the version of each plugin you were using? If you were using a dependency manager you wouldn’t have to remember because the original state of WordPress and all of the plugins would be stored in a configuration file in version control.
Composer is a PHP dependency manager and is the tool of choice when managing WordPress dependencies. Composer utilizes a simple JSON file for storing configuration and automatically pulls down any packages that have been declared as dependencies when you run
composer install. There are a few things you will need to know about setting up composer to work with WordPress, but once you get the hang of it you’ll wonder why you didn’t use it sooner!
2.4 Testing code
It is shocking to me how many WordPress developers don’t thoroughly test their code… or even just do basic debugging. At the most basic level, please just set
true in your
wp-config.php file. I can’t tell you how many times I’ve installed a plugin on my local environment and had it spew notices at me that the original developer never saw just because they didn’t turn on debugging. Andrew Nacin does a great job of explaining the basics of debugging in WordPress in his video on WordPress.tv. If you are a serious developer, you should be using an IDE like PHPStorm and running a debugger like Xdebug.
If you are creating a software product such as a premium theme or plugin, it is important that you test your code in as many different environments as possible. One way this can be accomplished is by having users beta test your code. However, you can also use tools like Vagrant to spin up virtual machines to test specific configurations.
Quality assurance in web development is the general process of making sure that the code you’ve written works properly and the user interfaces you’ve designed appear correctly in all browsers. This is an important step to ensure that you catch anything that might have fallen through the cracks. Often, this is a time consuming process where one or more people will look at a site or application in every browser and on every device they can get their hands on and interact with it. Thankfully, there are tools like Selenium that can help you automate these things. Even better, there are services like BrowserStack which handle all of the technical details and let you focus on creating something awesome.
2.5 Documenting code
Documentation is your first line of defense when it comes to support. Make sure that your documentation is somewhere that people will find it when they have a question and encourage people to check these sources before contacting you. Here are a few types of documentation you should consider:
- * Inline — Comment your code. Ideally you are using descriptive class, function and variable names in your code and your code speaks for itself, but it is still a best practice to utilize comments to provide more clarity.
- * Written — Traditional written documentation is still important. You should proactively provide instructions that give users an overview of the software and how they can use it.
- * Video — Not everyone reads documentation. People learn in different ways and you should be accommodating.
- * Contextual — WordPress provides contextual help in various forms such as splash screens, popups and help tabs. Think about how people will use your software and make sure they can easily find the guidance they need without having to go anywhere else.
2.6 Deploying code
An important thing to understand about code deployment is that the average WordPress user does it all the time. Every time someone clicks the ‘Install Plugin’ or ‘Update’ button, they are deploying code to their site. Web hosts such as WPEngine and Pantheon realize this and have created workflows that help prevent issues related to deploying untested code. The key here is that these web hosts provide you with a testing and/or staging environment where you can ensure that everything is working before sending things to your live production environment. If things fail, there are simple ways to undo your changes.
The key to deploying code is having a reliable workflow that reduces the chance that errors will occur. When errors do occur, rolling back should be as easy as batting an eye. Typically, there are a few different ways you can ensure code deployments go smoothly:
- * Use version control — The very nature of version control makes is easy to restore the code to any arbitrary point in time. The key with this approach is to make sure that you actually commit any changes that may have been made, such as when a user updates a plugin. Typically version control doesn’t include your database, which is a major issue. Thankfully, the Revisr plugin exists and solves all of these problems by not only tracking database changes, but also allowing you to commit plugin updates directly from the WordPress dashboard.
- * Use symlinks — This approach requires that you have the entire site in a folder and then as symlink, or pointer, that redirects the web root to that folder. When you want to deploy a new version of the site, just upload the new version into a separate folder and update the symlink to point to the new folder. The beauty of this is that there isn’t any downtime and if you need to rollback, just update the symlink to point back to the original site.
Best practices and the theory of relativity
Sometimes, best practices can be relative to your objectives. For example, if you are publicly releasing a theme or plugin, you will want to make sure that your theme or plugin will work for everyone who wants to use it. A best practice, in this case, is to find the common denominator. If WordPress currently supports PHP version 5.2, you probably shouldn’t be writing code that uses features from PHP 5.3 or your code will break on some web hosts. However, if you are writing custom code for a client and know that you will be deploying the code to a server that supports PHP 5.4, then it is perfectly acceptable to utilize more advanced language features in your project. In reality, best practices are nothing more than generally accepted methodologies and, in some cases, may not apply to you. The important thing is to understand the reasoning behind them so you can make an informed decision. But please, don’t take this decision lightly.