Any organization where multiple developers cooperate on a regular basis needs some guidelines to assure optimal quality of the end result. Most of these rules applies to freelancers as well.

[bjornad]

Coding Guidelines

Follow the official coding guidelines. Always! You may come up with very good arguments for deviating from them, but we need a well defined standard, so use these:

The WordPress Handbook also defines Inline Documentation Standards for PHP. Until official WordPress inline documentation standards for JS are published, I recommend using JSdoc.

Internal Plugin Directory

Keep an updated internal plugin catalogue. E.g.:

Tables: TablePress

Forms: Gravity Forms

Lazy Loading: BJ Lazy Load

JS and CSS concatenation: Minit

Add a short description of each plugin and how to set them up optimally.

You should also have a list of must-use-plugins and should-probably-use-plugins that you use for every, or almost every, project.

Functionality goes in plugins – presentation in the theme

All theme independent functionality, e.g. custom post types, should be placed in plugins. If certain functionality should never be disabled, put in a mu-plugin. The customer should be able to switch themes at any point without losing neither content nor functionality.

Likewise, all mandatory functionality for a certain theme goes with the theme.

Code for public release

All code, especially plugins, should be created as if it would be released publicly. This does not only give better code quality, but encourages reusability.

Use a private repo

All plugins that isn’t released publicly should be put in a private repo, so all existing customers can update their plugins from the WordPress dashboard when a new version is ready.

Facilitate for caching

Allow for full page caching for an arbitrary length of time by making sure that all GET requests can be cacheable. Load dynamic content with AJAX using POST requests.

Use Vagrant

Create an environment as close to the production servers as possible with Vagrant. You should also set up arbitrary server configs for testing, to make sure the code is as portable as possible.

Test on multisite

Make sure all themes and plugins works as expected in a multisite environment, as well as a regular installation.

Use WP_DEBUG

The constant WP_DEBUG should always be set to true on development – and always be set to false on production. If WP_DEBUG causes warnings in development, fix every single issue it complains about. If the warnings comes from a 3rd party plugin, you should either consider alternatives or fix the code and submit a patch.

Use the bundled versions of JavaScript libraries

Never replace the JavaScript libraries bundled with WordPress, like jQuery, with your own or any other versions. You are free to use a version hosted on a CDN, but make sure you load the exact same version of the library that your version of WordPress comes with.

Enqueue JS and CSS properly

Use the wp_enqueue_script and wp_enqueue_style functions for every single JS or CSS file you use. No excuses!

All strings should be translateable

Use the gettext functions for every single string.

Provide descriptions for translators

E.g. the word «post» can be both a verb and a noun, which in a different language can have two very different words. Provide descriptions for translators so they know what they are translating.

Create flexible themes

Just because your client have three products they want to showcase on their front page right now, doesn’t mean they don’t have four or two in six months. Make sure your theme doesn’t dictate the content, but is flexible enough to handle added or removed sections.

Keep the templates clean

At some point you’ll find yourself in a situation where you need to add logic to your template files. Make sure the templates are as clean and readable as possible by putting the logic in functions – not defined within the template file itself, but in functions.php or similar.

Write to the correct folder

Even though /media is the default folder that plugins should write any file to, WordPress can be configured to use a different folder. Make sure you write to the correct folder by using wp_upload_dir()

Use WP_Image_Editor

If your theme or plugin use a custom image size just for specific pieces of content, like a custom post type for products, you don’t need to fill up the disk space with unnecessary created images with add_image_size(). Use WP_Image_Editor to create custom sized images of just the ones you need – and cache the result.

Never rely on a resource being there

Never expect a resource – whether it’s an external API or an internal file – to be available. It might go offline, be deleted or moved. Always do checks first. If possible, recreate the resource. If not, work around it.

Cache at every level

Of course you cache results from external APIs, but you should also make sure you cache results from the database and generated output. All these caches are made on the server. But also make sure you cache results at the client level. The HTML5 API localStorage is excellent for this purpose.

Say you have a full page cache that only expires once a day, but you are displaying an Instagram widget on every page. The Instagram widget can be pulled in via AJAX, but the client doesn’t have to make that extra request on every page load. It can cache the widget in localStorage and only refresh it from the web server every 15 minutes or so.

Retry, not hammer

If your cache has expired and the external API is unavailable, don’t retry for every incoming request you got. Hammering doesn’t help neither you, your users nor the external API provider. Only retry at a set interval.

Tailor the admin to your client’s needs

Most of the time, the wise choice is to not give your client an administrator level account. You should rather give them an editor level account and tailor what that user level has access to and see in the WordPress admin interface.

E.g. if the client only needs to update pages, that is all they need to see in the backend.

Always agree with the client before you remove options for them, though. It might be a good idea to also give them an administrator level account (not named «admin» of course) that they don’t use on a regular basis, but keep for safety it they should need it in the future.

Don’t comment your code

– Wait, what?

– OK, let me rephrase that: Write your code so it doesn’t have to be commented.

Make sure everything is neatly structured. Use names for variables, classes and functions that is self-describing. Functions should do as little as possible and be as short as possible.

Then, comment your PHP code according to the WordPress PHP Documentation Standards and JavaScript according to JSDoc, to make sure your comments make sense and automatic documentation can be made from it.

Be protocol agnostic

Just as you should make no assumptions to where in the structure WordPress itself is installed or where the upload directory might be located, you should make sure everything works fine regarding of what protocol is used – or port for that matter.

Create – and use – unit tests

Yes, it might be tedious and sometimes take more time than write the code itself, but in the long run it’s worth it. As the complexity of your project grows, unit tests will actually save you time. And after all, chasing bugs isn’t fun either.

Never use temporary solutions

There is nothing as permanent as a temporary fix. Avoid hacks at all cost.

Credits & Thanks

Thanks to Noel Tock for his inspiring talk at WordCamp Norway 2014 on designing and customizing the UI for the client. The slides from his talk are available here.

Thanks to Drew Jaynes for pointing out that WordPress has inline documentation standards that supersede the phpDocumenter spec.

Thanks to Thomas Bensmann for letting me know about the JavaScript equivalent of PHPDoc/JavaDoc: JSDoc