How not to develop a site using the Features module
The Features module for Drupal is a powerful tool for site development, but it's got its share of challenges, as Lullabot's James Sansbury noted in an insightful piece on Features including dos and don'ts of using Features as a deployment tool.
Features lets you push configuration like content types, fields, blocks, and views from the database into code. At its best, it can provide a smooth and reliable means of building out configuration on a development site and then deploying it to production.
But it can also have you tearing your hair out, trying to remember who did what, which changes have already been captured, where those supposed "conflicts" came from, and why everything's suddenly showing as "overridden".
Here are some frequent problems and gotchas in features-based development and some brief tips about how to avoid them.
- Lumping disparate functionality together in a single feature. A feature is defined as "a collection of Drupal entities which taken together satisfy a certain use-case." The Features Plumber module aims to help with the task of breaking up poorly constructed features along more logical lines.
- Not tracking what changes have been made and need to be committed to features. This is especially true for variables, since what shows up in Strongarm for adding is a mishmash of every setting that's been saved, not in any way a list of what needs to be added to features. A good guideline is to add a variable to a feature only if the variable is (a) edited via a settings form, and (b) set to its non-default value. A good habit to get in is, when you are doing configuration, note the machine name of any variable you change from its default. (You can do this by, e.g., using Firebug to select the relevant form element and looking at its "name" attribute.) Then decide which feature that variable is relevant to and add it when you're regenerating the feature.
- Too infrequent commits of features changes. If you're looking at a huge diff with various and sundry changes, the tendency will be to commit without reviewing. Try to regenerate features often and make each new feature or bug fix its own commit.
- Making configuration edits on the wrong site (stage or live rather than dev). Doing so means the changes are lost, in that they won't reach features, and leads to overrides on the stage or live sites, meaning that further changes made on dev and pushed to features won't appear on the stage or live sites. Once you're working with features, you want to make all configuration changes captured in Features in a development environment, leaving your staging and live sites in a clean state, free of overrides.
- Creating or editing content, taxonomy terms, or other non-features-based data on the wrong site (dev rather than live). These data will be lost, and any references to them that make their way into features - e.g., a setting referencing a taxonomy term by ID - will be broken on stage and live. You need to make content changes on the live site and then pull a version of that database to dev--after all current features-based changes have been exported from the dev site, ensuring that you're not losing anything when you pull from live.
- Considering something "fixed" when it seems to work on the dev site. It's not fixed until it's been added to a feature, brought over to the stage site, and successfully tested.
- Not using a stage site. Pushing changes straight to live doesn't allow for essential QA testing.
- Blindly committing changes. It's important to look over the changes that have been made. Someone else on the site may have been messing around with configuration. If you're committing a change, it's your responsibility to understand it and know why it's been made.
- Letting dev get too far behind live. If the dev site isn't frequently synched with the live site's database, it can get too far behind to be an effective development ground. Required data like new taxonomy terms and content won't be available. Excess configuration may be in place on dev. Due to accumulating differences between dev and live, configuration pushed to features may be broken or look very different on live.
- Too frequent pushes to live. It's not necessary to be constantly pulling in changes from dev on the live site. Bundling changes and pulling on a schedule can allow for more control and rigour in the process.
- Lack of a branching strategy. It's essential to isolate live from major new development. It may be necessary to push minor fixes to live while bigger changes are in development. Branching can make this possible. In this case, it may be necessary to commit only partial features updates to a stable branch, while making larger changes in a development branch.
- Not reverting after regenerating. After each time a features is regenerated, its components should be reverted on all sites. Doing so ensures a clean database and helps prevent differences between different sites' states.
- Lack of coordination between different developers. It's difficult for more than one person to work on a given feature at a time, since changes may conflict and no one knows what all is being worked on or needs to be committed. A system like tracking who's "got" a particular feature at any given time can help.
- Not saving configuration in features-appropriate ways. Some configuration needs to be explicitly saved to a features-aware component. For example, if Spaces is in use, any overrides in a space must be explicitly saved to that space's preset before they will appear in a regenerated feature.
- Not regenerating before doing code-level edits. It's often handy to edit features at the code level, but as soon as you do so you'll need to revert them to get the changes recognized. Because of this, before you start to do code-level edits, make sure you have no uncommitted overrides, that would later be lost when you revert.
- Relying excessively on UI tools and manual workarounds. For day to day Features-based development, the Drush commands available for automated inter-site file and database syncing and features management are indispensable time savers.
- Using a version control system that doesn't work well with the Drush features commands. Because Drush backs up and then deletes feature directories before regenerating them, version control systems like SVN that add subdirectories to every directory are poorly suited. Moving to Git greatly facilitates Drush features management because Git doesn't save its information in each directory.
If you find this list intimidating, well, I have to say that in some ways it should be. Pushing your configuration to features won't in itself solve your deployment headaches, and in fact will require a fair bit of new work you didn't have to do before. That said, if you go into it with open eyes and ready to roll up your sleeves, Features can be an effective tool and also have numerous advantages, enforcing a new level of rigour in feature planning and site development.
P.S. This list assumes a typical dev > stage > live setup in which configuration changes are made on a development site, saved to features, and then brought to stage for testing and finally to live. Features can also be developed by individual developers working in their own sandbox sites, an approach that may have some advantages over a shared dev site in that it's easier to frequently update from the live database without affecting other developers' work.
