Date:
19 April 2016
Author:
Ivan Grynenko

Development tooling and best practice moves fast! This guide is outdated. An updated revision will be published in the near future.

Introduction

Drupal continues to be adopted as a pillar in government and corporate digital content management. Government is increasingly adopting, and benefiting from, open solutions (open-source) and rationalised approaches such as govCMS. Large organisations are formulating plans to release themselves from vendor proprietary solutions such as SiteCore, Adobe, IBM WCM, Squiz, etc. This change in market dynamic is being supported by companies such as Acquia that offer enterprise-grade support services, such as resilient hosting, SLA-backed guarantees, etc., for Drupal. Salsa Digital is also facilitating this market change via the provision of digital strategy, design and engineering/build skills for Drupal sites in general, but more specifically those hosted on Acquia and govCMS.

Salsa Digital is an enterprise ‘government-grade’ digital agency with a strong, 13-year legacy in open-source web design, build, hosting and support projects. Salsa Digital prides itself on RIGOUR - one of our seven key core cultural values - not just with how we engineer solutions but also supporting processes. This technical white paper provides some insights into that level of rigour in the context of enterprise-grade quality considerations for Drupal projects and their execution.

Initial development environment setup

To avoid individual developer or environment-specific issues, make the development setup unified across the entire web development department. To achieve this, we use Vagrant box to run virtualised servers, packed with all the tools required. We use the same set of tools and IDE, along with unified coding standards.

LAMP stack vs Vagrant virtual boxes

In our practice, use of Vagrant virtual boxes, built with tools such as Ansible/Packer or Puphpet will reduce risks of individual issues, ensure all developers use the same development server configuration, and eliminate any waste of time for the initial setup and ongoing updates of the development environment. This approach minimises differences between operating systems (e.g. Windows and Mac OS could work well together).

Making single Virtualbox/Vagrant VM per project allows us to accommodate the unique configuration required for each project.

To get the Ansible/Packer Vagrant box, check this project https://github.com/beetboxvm/beetboxExternal Link or head to https://puphpet.com/External Link to configure your Vagrant VM online.

The vagrant box configuration is typically stored at the root of each project in a subfolder. The web root should be placed into a subfolder (such as www/ or docroot/) to keep your project root folder clean.

Extras

Make efficient use of:

  • drush;
  • Composer; and
  • Drupal console (Drupal 8).

Unified IDE

Having single IDE used by your entire development team makes collaborative work more efficient. Having an IDE that incorporates tools for writing clean, quality and efficient code improves maintainability of your software even further.

In our practice, PHPStorm provides multiple inclusions to achieve that objective. It has built-in Drupal integration, debugging capabilities and code quality control tools. When used by the entire development team, its configuration could be shared across the organisation to enable every developer using the same style for PHP, JS and CSS/SCSS/LESS.

Code debugging

PHPStorm comes with built-in PHP debugger, one of the best tools that many developers miss. As a general guideline, do not print your debug functions in code, use debugger instead. Functions like print(), print_r(), var_dump(), var_export(), kpr() become a time bomb and may turn into a white screen of death or print debug code on production servers.

Code quality control utilities

To help your team write quality code and Drupal coding standards compiled code, we recommend deploying tools for checking the code syntax.

In our practice at Salsa Digital we use these tools (all tools are based on the PHP_CodeSniffer library and provide similar output):

Writing clean code is the key. The Drupal coding guide pages is a good place to learn for basic coding principles. Avoid wrapping Drupal API in complex OOP implementations. It reduces maintainability of code tremendously. Keep your code simple, so that developers of any level could work with it.

  • Do not overcomplicate your custom code.

  • Make sure custom code is easily understood by developers of any level.

  • Make efficient use of template files and theme functions.

  • Avoid PHP code in template files.

  • Do not overcomplicate your code with multiple if/else conditions.

  • Make efficient use of getter/setter functions.

  • Do not commit commented code.

Quality control workflow

Pull requests (code review)

To ensure quality and compliant code, we recommend making efficient use of PRs (pull requests) as part of your development workflow. Pull requests require accounts in either GitHub or Bitbucket.

A typical PR practice fits into normal development workflow like this:

  1. A developer works on one ticket at a time, in a corresponding git feature/ branch.

  2. When a developer completes a ticket, you should run a code quality control utility (e.g. dcr) and correct any warnings discovered, to ensure the code is compliant with the coding standard.

  3. Merge the latest develop branch into the local feature/ branch.

  4. Test the ticket to satisfy the acceptance criteria.

  5. Push the feature/branch to a remote git repository (e.g. Bitbucket or GitHub) and create a pull request against develop branch.

  6. The pull request needs to be reviewed by one or two other developers and be either approved or declined. In the first case the code is merged into the develop/branch. In the later case the developer implements any feedback suggested in the pull request, and then pushes code changes to the remote repository for the code review to resume. This process repeats until the pull request is approved.

  7. Developer begins work on another ticket, always forking off the latest develop branch. It is a good practice to restore the database to the official “locked” version (see further down) at the beginning of work on a new ticket.

Git

We recommend following Gitflow workflow. It perfectly suits modern software development and release process.

Check these pages to learn more about Gitflow:

Naming your feature branches consistently

When creating feature branches, plan your feature branch naming pattern and request all developers to follow it. For example, every ticketing system uses a ticket ID. In our practice, naming feature branches as feature/[ticket-id] has proven to be a reliable and clean way to map a ticket to a git branch. If more than one branch is required to complete a single ticket, append your branch name with incrementing numbers, e.g. feature/[ticket-id]_0.

Unified commit message pattern

When committing code, we recommend to prepend commit message with the ticket id, starting commit message with a verb and ending it with a full stop. For example, a commit message like this: “[BUG-EG-02] Fixed spelling in a sentence.” makes it easy to read, understand and find in the git log. Always provide descriptive commit messages. Avoid committing multiple fixes in one commit, this makes it harder to cherry pick commits when required.

Git tools and risks

When it comes to gitflow use, we recommend using a single software to manage your git workflow. We’ve found SourceTree to be a great app that is cross-platform and has built-in support for Gitflow, git submodule and git subtree.

Note about terminal use. Terminal is a very powerful tool to manage git in any required way. However, terminal provides limited visibility, is prone to human errors and may be very unforgiving. We do not recommend using terminal for git management.

Release management

Gitflow was built with release management in mind. We recommend sticking to gitflow’s built-in release management workflow.

Make up your mind about release naming patterns. Some examples of naming your releases are:

  • Release_cycle.week_number.release_attempt. E.g. 1.03.00. The release cycle increments every year. Use a two-number week number. The release attempt allows you to release sequential hotfixes if bugs are discovered immediately after the release.

  • YYYY-MM-DD.release_attempt, e.g. 2016-03-30.00.

  • Release_cycle.release_number.release_attempt, e.g. 1.00.00, where release number is an incrementing number that increases every release.

When closing the release, Gitflow creates a release tag. Always deploy the release tag, avoiding using branches in production. Acquia is a good example of best practices in release management: it uses tags and allows easy reversion to the previous release tag when required. It is good practice to make a full database backup prior to the release deployment.

Entities relationship diagram

Before beginning a website build, we recommend preparing a detailed entity relationship diagram (ERD) for all content types, file entities, taxonomy terms and any other custom entities to be implemented. The diagram should reflect the proposed entities’ structure and any custom field names. The ERD is the biggest planning effort and allows you to streamline the development process, avoiding dead ends and structure roll backs.

Entity field names

Consider giving meaningful, short names to any custom fields added to entities. Based on the type of entity, consider prefixing field names as in the following example:

  • Users: field_user_[short_field_name]

  • Nodes: field_content_[short_field_name]

  • Taxonomy terms: field_term_[short_field_name]

To avoid data duplication and reduce database size, it’s best to reuse existing fields as much as possible.

Responsive theming

These days no one develops responsive themes from scratch - rather, proven responsive frameworks are used. Good examples are:

All of these frameworks have base themes available for Drupal, and they’re free.

Front-end developers should spend time learning the grid system, available built-in classes, CSS and JS libraries, rather than reimplementing features that are available out-of-box. We have seen a lot of these in the past. Encourage your front-end developers to refer to the wiki pages of the selected responsive framework.

Database structure versioning

To ensure developers don’t encounter issues with different database versions, export the database configuration using Features module and version it in Git. To achieve fluent development workflow, ensure all developers use the same version of the database. This version of the database should be “locked” at the beginning of each sprint or release cycle. Any changes to the database should be implemented via code (using hook_update_N()), which brings every developer up to date after running any pending updates. When a developer completes a ticket and begins a new ticket (forking off the develop branch), it is good to revert the database to the “locked” version.

At the end of each sprint a new “locked” version of the database is prepared and shared with all developers. A good way of sharing the database is via an exported Vagrant box, hosted internally or externally (for example you may prepare your Vagrant box locally and upload to Atlas: https://atlas.hashicorp.com/help/vagrant/boxes/distributingExternal Link ).

Unified coding standard

For any custom theme and module implementations, follow the unified Drupal coding standard: https://www.drupal.org/coding-standardsExternal Link .

To confirm your code is compliant with the Drupal coding standard, use tools like dcr (see above).

Writing secure code

Writing secure code should be the first priority. Follow this guide to write secure code: https://www.drupal.org/writing-secure-codeExternal Link

https://www.drupal.org/node/28984External Link

The Security Review module could help identify insecure code or other security problems with your website: https://www.drupal.org/project/security_reviewExternal Link

Site audit

During the website pre-launch stage, review your website to address the following concerns:

  • Drupal Best Practices - structural recommendations

  • Block - caching

  • Cache - optimal Drupal caching settings

  • Codebase - size of the site; size and count of managed files

  • Content - checks for unused content types, vocabularies

  • Cron - Drupal's built-in cron

  • Database - collation, engine, row counts, and size

  • Extensions - count, development modules, duplicates, missing

  • Insights - analyse site with Google PageSpeed Insights

  • Security - check for common security exploits, such as malicious menu router items

  • Status - check for failures in Drupal's built-in status report

  • Users - blocked user #1, number of normal and blocked users, list of roles

  • Views - caching settings

  • Watchdog - 404 error count, age, number of entries, enabled, PHP errors

The Site Audit module might help to identify some of problems with your Drupal site build: https://www.drupal.org/project/site_auditExternal Link .

Contribute to the Drupal community

We advise against patching Drupal core or contributed modules. If bugs are discovered in any of the contributed modules, it’s good practice to fix it and upload the patch to the project page on drupal.org. If you use drush make file, include the reference to your patch in the make file, to enable automated builds.

Drupal provides a variety of ways to alter existing functions provided by its core modules or contrib modules. Consider using alter methods to override existing functions, rather than patching modules.

Risks matrix

When running a project, keep in mind some things to avoid:

What to avoid

Risk level

Reason

Patching Drupal core or contrib modules

High

  • Compromising website security

  • Reducing maintainability of the code

  • Main source of unnoticed bugs

Writing insecure code

High

  • Compromising website security

Wrapping Drupal API with custom code, e.g. custom OO API to replicate Drupal API in more familiar way

High

  • Reducing maintainability of the code

  • Compromising website security

  • Performance penalties

Using server variables directly

High

  • Compromising website security

Raw PHP, Bypassing Drupal API

High

  • Compromising website security

Using PHP code for debugging (e.g. kpr(), var_dump(), etc.)

High

  • High chance of critical errors in production environment

Avoid using PHP filter, do not enter PHP code in nodes, views, blocks or any fields in browser

High

  • High chance of critical errors in production environment

  • Possibility of breaking cron job

  • Inability to index website (search)

Acquia hosting: don’t introduce reliance on Composer

High

  • Acquia does not support Composer

Acquia hosting: don’t use Git submodules

High

  • Acquia does not support Git submodules

Using PHP logic in template files

Medium

  • Reducing maintainability of the code

  • Compromising website security

Use of session variables for anonymous users

Medium

  • Session variables will bust the Varnish cache, reducing performance

Drupal coding standard compliance

Low

  • Makes code easily readable by any Drupal developer

Inconsistent setup of development environment

Low

  • Increases setup times

  • Creates lack of essential tools

  • Version-dependent issues

  • OS-dependent issues

Multiple IDE used across the team

Low

  • Reduces effectiveness of team collaboration

Not using responsive framework

Low

  • Increases development effort on re-implementing existing features

  • Increases QA times

  • Increases number of issues/bugs

Recommendations matrix

When planning or running the project, consider the following recommendations in order of importance:

Recommendation

Importance level

Description

Plan site structure ahead (ERD)

High

  • Streamlines development effort

  • Minimises roadblocks

Use features module to export and version control site structure and config

High

  • Streamlines development effort

  • Allows to version site configuration and structure

Override Drupal or contrib modules via hooks where possible

High

  • Improves maintainability of the code

Use hook_update_N to revert features

Medium

  • Streamlines development effort

Setup unified development VM

Medium

  • Streamlines development effort

Make use of Drupal console project

Medim

  • Streamlines development effort

Use proven workflow (e.g. Git flow)

Medium

  • Minimises chance of human error

When selecting contrib module, consider last updated date

Medium

  • Avoid use of obsolete modules

Plan layout of project folders

Medium

  • Minimises roadblocks

  • Improved collaboration

Use IDE with debugging capabilities (PHPStorm or similar)

Medium

  • Streamlines deployment

  • Minimises chance of human error

Use drush make file to maintain modules and patches

Low

  • Streamlines deployment

  • Minimises chance of human error

Create a README.md for developers

Low

  • Assists new developers or maintainers of the code in understanding the development process used on the site

Get the latest digital insights and Salsa news

For a roundup of the latest news and insights across digital government, web development, open data and open source please subscribe to Salsa's monthly newsletter. 

Subscribe to our newsletter