Drupalcon 2011: Code-Driven Development: Using Features Effectively
One of the biggest barriers to using Drupal effectively is managing the Dev->Test->Production->Update lifecycle. Most problematic is making structural changes to a site already in production. You don't want to break/modify production while live, you don't want to blow away data by copying data from Dev to Prod, and you don't want to try to make the changes in two places. Based on my readings, I had decided that Features would play a major role in solving this problem. The training class presented by Nuvole
today showed that Features can make life-cycle management much, much, easier. In fact, as best as I can tell, code-driven development is the
way to produce, manage, and deploy enterprise-quality sites.
Nuvole has posted slides on SlideShare
. (These may not be the exact slides used at Drupalcon, as they seem to be a few weeks old, but look very similar to what I'm seeing on the screen.)
Thanks to Antonio and Andrea for a great presentation -- it was really content-rich, and they managed to work through the technical glitches of student laptops quite smoothly.
These are general notes from the presentation:
Introduction & Motivations:
- Fast Delivery -- Multiple Developers
- Safe Updates for Configuration
- Change Management
- Pushing Upgrades to Production SItes
- Code Driven Development
- Database for Content Only
- All Configuration in PHP
- DB Dump from Production to Development, NEVER the other way
Interesting Nuvole Practices
- Nuvole bases most themes on Tao from Development Seed
- Nuvole uses OpenID, and even uses it for uid 1.
- Nuvole SEEMS to develop locally (per-developer), then stage/test on a dev server, then push to production. (Never explicitly stated.)
- Nuvole does not yet use a features server.
- Nuvole wraps contrib modules in features (so they can be auto-installed, updated, etc.)
- Page editing with Markdown syntax
- Nuvole has a feature (feature_site) that they use on most sites to set up some defaults for their workflow.
- Mostly customizing OpenAtrium
- Use typically 4-5 features on top of OpenAtrium
- More custom sites use 10-12 features typically
Technical (Features & Code-Driven Development)
- Package Functionality in a Logical Way
- Be Modular -- break things up cleanly
- A single item should be included in only 1 Feature
- Reusing components (e.g., imagecache presets) across features may result in undesired changes to feature B when updating feature A
- UI will not present items already included in other features (e.g., UI only presents items only in DB)
- Open Atrium is completely based on Features
- "Drush is faster, of course." -- Favorite Quote of the Day
- Features may depend on other features or on modules
- Managing features with drush is faster than GUI.
- Out of the box component support:
- ImageCache presets
- Feeds Importers
- Variables exported via Strongarm, but need to figure out name of variable (drush saves the day again)
- CTools used to produce many exportable features. (No need to reinvent the wheel.)
- Exporting components that are not natively exportable is non-trivial
- No known way to export taxonomy TERMs safely. (Generate in code?)
- Some things export with numeric ID, which is dangerous (blow away others with same ID)
- String ID is better, or UUID
- Most exportables have some form of hook_alter that allows them to be modified by other features.
- CTools provides many hook_COMPONENT_alter().
- Ideally (not required) prefix component names with the name of the feature. e.g., for a blog feature, view could be blog_view, content type could be blog_entry, etc. (Names can be duplicated, so just blog would be ok for these, but more complex features may use >1 content type or view)
- 3 states for Features
- Default = no DB entry or DB matches code
- Overriden = code is unchanged, DB is used to override code (NOTE: could be updated code from previous Default state)
- Needs review = code has changed AND DB has changed (like SCM conflict, requires manual fix)
- Features does not touch .module
- "UI is messy to update features" -- use drush to update; only use UI to build new features initially
- Sites using "advanced" features will require PHP knowledge
- Drupal "makefiles" download needed modules for you, can apply local patches, patches from drupal.org (bootstrapping)
- Collaborative development cycle (many dev installations of same site)
- Use hook_update_N() to perform updates in collaborative development cycle
- Each developer needs to run svn update && drush updatedb && drush cc
- Poses problems when pulling new copy (svn co)
- Structural updates in both hook_update_N() and hook_install()
- features_install_modules is superior to drupal_install_modules
- Version control conflicts detect use of same update code, allowing developer to resolve conflict.
- Use "controller" feature to manage dependencies, updates
- One controller feature per site
- Default feature as well (e.g., Nuvole, KSU; entity-oriented)
- In Drupal 7, Installation Profiles are more like modules
- Replaces controller feature (can run updates in installation profile)
- Can be used as more of "site profile"
- Still use controller feature if working off another Installation Profile
- Makefile useful to remind developers where things come from, so useful even if you're not using drush make.
- Hacked! module only looks at drupal.org, does not consider makefile.
- Only use Installation Profile for Distributions, others build in sites/all.
Other Cool Things
- Update module is very slow -- turn off in production
- Unsure of performance comparison between in-database and features, but no significant difference from empirical/qualitative standpoint
- Do not write modules that use numeric IDs if they should be exportable