Blog

Feb 2010 02

James Sansbury

Easy Install Profiles

Did I really just say that?

While many people lament Drupal being a product somewhere between a content management framework and a content management system, it’s often in these less than ideal situations that remarkably creative solutions are born. Examples of this are CCK, Views, Features module, and the list could go on. If it weren’t for the painstaking nature of writing SQL in the “Drupal Way”, Earl Miles might have never created the Views module. If it weren’t for the fact that it’s virtually impossible to have a clean dev/staging/QA/prod workflow with Drupal, Development Seed probably wouldn’t have even dreamt of the Features module.

This brings me to install profiles. Those of you who’ve written them before know that things are not as simple as they seem. The system in its current state is not easy to implement. Forced into alternate solutions by the constraints of this system, we’ve come up with a API design for install profiles patterned loosely after Drupal’s theme layer.

What?”

Yeah, so that doesn’t make much sense does it? Let me try to explain. Drupal’s theme layer functions kind of like a hierarchical visitor pattern. For instance, say you use Zen as your base theme. To create a new sub theme of Zen, in the dot info file of that theme you would write:

name       = Fancy
base theme = zen

There you see the base theme is Zen. You get all the niftyness that Zen includes but then get to modify it and add new things if you’d like. Now if you tweaked out this sub theme and added all sorts of custom specialryness, you could then create another theme and have that theme be a sub-theme of your second theme:

name       = Fancier
base theme = fancy

So what if you could do something similar with install profiles? We asked the same thing…and then we tried to answer that question. In the process of building any custom project, you end up repeating many things. For instance, how many Drupal sites have you built that didn’t have Views and CCK installed? While drush does speed up the process of enabling all these modules, you still have to remember to do it every single time. Granted the chances of forgetting to enable Views is slim, but certainly there are other modules in your workflow that you overlook until some point later in the development process when you are asking yourself, “Now why is that not working?”

I know we’ve done that. So we have an install profile internally that loads up a file that sets a foundation for our typical custom site, much the way the Zen sub theme helps you easily create a new sub theme. Here’s are some portions of our ‘basic.info’ file that any custom site starts from:

Basic Info

name  = Basic
core  = 6.x
theme = fancy

Modules

modules[core][] = filter
modules[core][] = help
modules[core][] = menu
modules[core][] = node
modules[core][] = path
modules[core][] = php
modules[core][] = system
modules[core][] = user
; Contrib
modules[contrib][] = admin_menu
modules[contrib][] = date_api
modules[contrib][] = imageapi
modules[contrib][] = imageapi_imagemagick
modules[contrib][] = imagecache
modules[contrib][] = imagecache_ui
modules[contrib][] = token
modules[contrib][] = external
modules[contrib][] = globalredirect
modules[contrib][] = content
modules[contrib][] = fieldgroup
modules[contrib][] = filefield
[snip…]

So far this is pretty basic, just listing some modules and setting the theme, but here’s other things that go in our file:

Input Formats

input-formats[WYSIWYG][wysiwyg][editor] = tinymce
input-formats[WYSIWYG][wysiwyg][settings][default] = 1
input-formats[WYSIWYG][wysiwyg][settings][user_choose] = 0
input-formats[WYSIWYG][wysiwyg][settings][show_toggle] = 0
input-formats[WYSIWYG][wysiwyg][settings][theme] = advanced
[snip…]

Variables

variables[site_footer]    = 1.800.123.4567
variables[site_frontpage] = node/1
[snip…]

Menus

menus[menu-footer-links][title] = Footer Links

menu-items[login][link_path]  = user/login
menu-items[login][link_title] = Login
menu-items[login][weight]     = 10
menu-items[login][menu_name]  = menu-footer-links

menu-items[logout][link_path]  = logout
menu-items[logout][link_title] = Logout
menu-items[logout][weight]     = 10
menu-items[logout][menu_name]  = menu-footer-links

menu-items[front][link_path]  = <front>
menu-items[front][link_title] = Home
menu-items[front][weight]     = -10
menu-items[front][menu_name]  = primary-links

Pretty cool, huh? So then when we start a custom project for one of our clients, we can just create a new dot info file and base it off of what we’ve already built:

name  = Widgets R Us
core  = 6.x
theme = widgets_theme
base  = basic

; ------------------------------
;        Modules/Features
; ------------------------------
modules[contrib][] = views_customfield
modules[contrib][] = typogrify
modules[contrib][] = draggableviews

modules[custom][] = widgets_site

features[] = store

All we’re doing here is just adding a few more modules to what basic already described. The nice thing about this is I can keep honing the basic.info file every time I work on a new custom project.

The install profile that does all this magic isn’t publicly available yet, but if people seem interested, we are easy to persuade. :)

Jan 2010 21

Jared Ponchot

Sprocket's feature building toolbox

A simple listing of great tools for building features

After my last blog entry on creating and extending features, it occurred to me that a shorter listing of just the favorite tools we use in building features might be a nice help for some.  So here goes.  Please comment and let us know of other fantastic tools you use in your feature building toolbox.

Open Atrium:

We plan all our features first with the hopes of knowing what we’re getting into (node types, fields, views, contexts, etc.).  Usually this helps us avoid repeating mistakes we’ve already made.  SprocketLabs is our fancy schmancy name for our online project management tool.  It’s really just Open Atrium.  SprocketLabs is where we document and plan our features and manage just about everything we’re doing.  The incredible guys at Development Seed have outdone themselves once again with Open Atrium.

Omnigraffle & Stencils:

Unless the feature is something dead simple (ex. little to no user interaction) we typically wire-frame each full node display, view display, etc. ahead of time so we can think through how things will output, in what order, in what region, in what context, etc., etc.  I’m still searching for a simpler tool for wire-framing, but for now I’ve been using Omnigraffle and Konigi’s wire-frame stencils.  Honestly, a pencil and some paper is still my favorite way to wire-frame, I just haven’t figured out a super quick way to get my paper on Atrium for client approvals etc. (scanning is annoying).  For simpler wireframes I’ve also used the Web Sketch stencils.

Demo:

This module is really poorly named (in my humble opinion) and would be better named something like “snapshot,” which I realize is now the name of another backup module for Drupal.  The value of demo module in feature creation is that you can create an initial snapshot of your site, without the various elements your feature will provide (ex. node types, fields, etc.).  You then build your feature and, once completed, revert back to your snapshot quickly and try out your new feature.  It essentially lets you save everything at a point and time (database included) into a snapshot and switch quickly and easily between various snapshots.

Drush:

If you haven’t yet heard of drush or begun using it you need to check it out.  There are some super smart dudes that created and maintain this project and standing on their shoulders is a no brainer.  Regarding features and drush, commands like drush vget can be real time savers in feature development.

Variable Dump:

Variable dump does exactly what it sounds like.  Like Drush, it’s a very nice tool for quickly getting your variables output when extending your features.

Devel Feature:

Ok, so this one is a feature that we made ourselves and not a module.  This feature is also as much for general Drupal development as it is for just feature development.  Here’s what we did.  Our devel feature does the following when enabled:

  • enables Devel module
  • enables Demo module
  • enables Context UI
  • enables Views UI
  • enables Diff module
  • enables Rules Admin
  • creates a sitewide context that shows specific blocks for user 1 (ex. context devel block, devel execute php block, devel switch user block)
  • turns OFF preprocessing on javascript and CSS (via strongarm)
  • turns OFF page caching (via strongarm)

Also, when you disable the feature, it disables what it enabled and turns on what it turned off.

Coda Clips:

If you’re like us and use Coda, then you know clips can be a HUGE time saver.  James recently posted his Coda clips via github for all to use.  Many of his clips are just Drupal dev related, but some can be great examples of how to use clips and save some time. We realize some of you are not on a Mac or using Coda.  If you’re using BBedit, Textmate, or Komodo there are similar options (although not called clips probably) and the same sort of thing will still be a great time saver for you.

There’s the short list.  Let us know via comments what’s in your toolbox.

Jan 2010 20

Jared Ponchot

Creating & Extending Features

AKA - don't rebuild the same thing 20 times

Back in October we (James and myself) went to the fabulous DrupalCamp Atlanta and taught a session on creating and extending features in Drupal.  At the time, we didn’t have our fancy new website to blog on, so I thought it might be nice to write about that now and provide a quick summary of the high points and some organized notes.

In the session, we created a simple gallery feature as a demonstration of the key concepts.  Thanks to the fabulous features module developed by the magicians over at Development Seed we’re now able to take commonly used functionality, etc. and easily save it all into code for reuse (ex. node types, views, contexts, permissions, dependencies, rules, etc.).  This has saved us a ridiculous amount of time here at Sprocket and allowed us to devote more of our time and energy to making incredibly beautiful user experiences for our features instead of rebuilding the same functionality each time.  Feel free to go to the DrupalCamp Atlanta website and watch the video of the session.  The outline of what was covered includes:

  • Outline your feature (node types, views, contexts, permissions, dependencies, rules, etc.)
  • Consider your name spaces carefully!
  • Build your node types, views, contexts, rules, permissions, etc.
  • Create your feature
  • Extend your feature with CSS

Outline your feature

When building a feature, it’s always a good idea to first outline its parts.  A great way to approach this is to simply list out all of the following that will be a part of your feature

  • node types
    • fields
  • views
    • displays
  • contexts
  • rules
  • permissions

Consider your name spaces carefully!

Remember when creating your features that your type names for node types need to be unique.  For example, if you’re creating a gallery feature and your node type is an album, you may not want to use “album” as your type name.  Why?  What if you want to use your gallery feature on a site that is a musician’s site, and you’ve also created another feature to show off their albums and it also has a node type with a type name of “album” in it?  Both features won’t play well together.  A good practice is to prefix in ways that add specificity for your feature.  For example, your gallery feature might have a node type of “gallery_album” and your music artist feature might have a node type of “audio_album” for example.

This same concept also applies to the name spacing of your fields.  Unless you want all the settings on a field to be exactly the same in all features with that field, then you need a unique name space for your field.

This may seem obvious, but this ALSO applies when you get ready to name your Feature itself and give it a machine name.

Build your node types, views, contexts, rules, permissions, etc.

This part is pretty self explanatory if you’re already doing these sorts of thing with Drupal.  The beauty of Features is that once you’ve done these things you can package it all up into a nice and tidy feature module to reuse on another site or for another project.

Create your feature

Before you can begin extending your feature, you need to first create it.  While this can be done by hand, features offers a nice UI that makes it pretty fast and simple for those that don’t have access to Drush.  Remember that you have to actually have the nodes with fields there, the views, the contexts, the permissions etc. before you’ll be able to select them in the features UI.

Extend your feature

This is where I felt the real meat of our DrupalCamp session was.  Once you’ve got a feature, since it’s just a Drupal module, you can extend it in a number of ways beyond what’s currently available via the features UI.  A few examples include:

  • Use hook_strongarm to set some variables
  • Use hook_init to add CSS that loads with the feature

Add some strongarm settings

Strongarm provides a great way for your feature to enforce some variables.  While some would argue against the obtrusive nature of that, in certain use cases it’s a wonderfully simple solution.  For example, if you want a twitter feature where the feature is already set to work in a specific way (which node types to include, etc.) and the only thing you want to allow/require users to set is their twitter account info, strongarm makes that possible.  This means a user can enable the twitter feature and only have to do one quick task and they’re ready to go.  Another fantastic tool for getting your variables you want to strongarm, check out the variable dump module or use drush vget [variable name].  Once you’ve got some variables you want to strongarm, do the following:

  1. Open your features .module file.
  2. Use hook_strongarm to add your variables (see example at bottom of post from my fancy_twitter feature).

Add some CSS

In many cases styling is tied more to the theme rather than the functionality itself or the feature.  However, in some cases it’s nice to have some styling already preset for a given feature.  It’s pretty easy to do this as well, simply:

  1. Open your features .module file.
  2. Use hook_init and drupal_add_css to add your CSS file to your feature module (see example at bottom of post from my fancy_twitter feature).

Note: When updating your feature in the future, features module will continue to include the extended code you’ve added to your .module file, but it will NOT grab your actual CSS file and include it when tarring up your feature module for you.

Example implementation of hook_strongarm()

<?php
/**
* Implementation of hook_strongarm().
*/
function fancy_twitter_strongarm() {
  return array (
   
'twitter_api_url' => 'twitter.com',
   
'twitter_expire' => '0',
   
'twitter_import' => 0,
   
'twitter_set_source' => 1,
  );
}
?>

Adding CSS with hook_init()

<?php
/**
* Implementation of hook_init().
*/
function fancy_twitter_init() {
 
drupal_add_css(drupal_get_path('module', 'fancy_twitter') .'/fancy_twitter.css');
}
?>

Conclusion

There’s a lot more I could go into here, but I’ll leave it at that for now.  James is our Drupal magician here at Sprocket and perhaps soon I can get him to do an advanced blog post on further extending features.

Dec 2009 17

James Sansbury

Avoiding Technical Debt (Part 2)

Additional tips on how to avoid technical debt in your endeavors.

This is Part 2 of a discussion about Technical Debt.  Here I’ll discuss some more tips on how to avoid it.  If you haven’t read Part 1, get going!

Be consistent

Being consistent is not easy.  We are always refining our processes, finding better ways to accomplish our tasks.  Our processes will never be fully consistent, but that doesn’t mean we can’t strive for consistency in them.

Namespacing: Have a consistent way you name your files, your folders, your views, your fields.

Structure: Having a consistent directory structure for your modules and themes will save you headaches later, as you can more quickly find what you are looking for.

Write it down

One of the inspirations for writing this post was stumbling on a theme override function in one of our themes.  I looked at the function and thought to myself, “Now why did I override this function?”  If I had taken five seconds at the time to write down in the DocBlock why I needed to override the function, I wouldn’t have had to search in the module for the original function and track down what was different.  This is a prime example of Technical Debt.  Saving those five seconds then cost me about 60 seconds today as I had to look up the function to see if it was necessary anymore.  Comment liberally!  You will never regret writing too much commenting into your code.

CSS: CSS is probably one of the easiest places to incur technical debt since the actual order of the CSS is crucial to the styling.  You can’t just pop open a style sheet and start re-ordering styles without potentially breaking the cascade.

Things I try to always comment within CSS:

  • When using em spaces, I usually comment in the actual pixel value I’m shooting for, and the calculations I made to arrive at that number
  • Any IE specific hacks and why they were necessary
  • Seemingly unnecessary declarations:  there are lots of times that I’ll pull open a CSS file and look at a height declaration, say, and delete it thinking it unnecessary, only to find there was a very good reason for it to be there.  Comment!

Somewhat of an annoyance is the lack of a quick commenting method in CSS files.  You have to wrap any comments /* like so */.  Create a snippet and shortcut key in your IDE or text editor that will quickly add the comment for you.  You want to make it as easy as possible to comment, so laziness won’t get the best of you!

Todo lists:

Get a good GTD app (I use OmniFocus) and keep it synced between your various computers.  When you need to do something and you can’t do it right then, write it down!  Not only that, but take the time to write it as if you were writing it to someone else; don’t just assume you will remember what you meant by, “Clean out line 32 and check load time.” 

Keep it simple

Simplicity and minimalism will create more ‘white space’ on your technical canvas.  Writing a web application?  Write down all the desired features, prioritize them, and then weed out everything that is not crucial functionality.  Build the foundation of necessary features, and then expand onto that once the foundation has proven itself.

Focus! Writing code requires your concentration.  Turn off Twitter, IRC, Chat, your email, yes, even your phone.  Set specific times throughout the day to take a break from writing code and check those things.  Ask co-workers to postpone non-urgent questions (but give them a specific time when they can ask you questions!).  You will feel the effects of that space, and it will help you to work in a less stressed way.  You will find it easier to actually spend that extra 5 seconds writing down comments, or splitting a large module file into separate includes.

Experience Freedom

I hope these tips were helpful, and that you will soon be experiencing freedom from the weight of your technical debt.  I look forward to reading comments on other ways you avoid technical debt in your endeavors.

Nov 2009 25

Jared Ponchot

design or develop, which should come first in your drupal workflow?

We're still on the journey here at Sprocket, so here's some thoughts from the road.

Let me begin with the following disclaimer:  This brain dump is neither exhaustive or heavily researched.  I’m quite certain there are valuable articles already written on this topic, so if you know of any please let us know via comments.  I’ve wrestled with this issue for a while and haven’t yet found many writings on it.  That being said, here’s some thoughts from what we’re learning here at Sprocket.

Neither is first

This is probably stating the obvious, but just to be sure we’re clear, neither design or development comes first.  Site planning is the first step for every custom project we take on.  Whether our client has already done site planning or we’re asked to assist, any way you slice it, you have to do some planning.  Content structure, types of content, roles, features, wire-framing, etc. all need to be fleshed out before you can even begin designing or developing (although in my opinion planning is actually part of design and an essential element - but I digest).

Sprocket’s design priority

At Sprocket, we view ourselves as a design agency that does development along side, and not the other way around.  That’s not to say we feel we’re poor at development - quite the contrary.  Our genesis was as a design agency and I feel we approach problems more from a designer’s vantage point than a developer’s.  That may largely impact our views on this issue from a gut reaction standpoint, but what I’m finding is that it really doesn’t alter the fundamental problems that can arise in our workflow.

What makes a project successful?

To figure out which workflow fits best, I think it’s helpful to first determine what makes a project successful.  If the goal is successful projects, then developing good workflows becomes a strategy for achieving that goal, and specific workflows are tactics to support that strategy (although you could break that down differently I’m sure . . I’m just a designer).  One of the questions I’m trying to ask going into any project is “what are the metrics for success?”  We want to know what the client’s answer to this question is.  However, your client is not the only one with an answer to this.  Here’s a quick list of just a few things that I believe are crucial for Sprocket to deem a project successful.

  • profitable - This is pretty self explanatory.
  • portfolio-worthy - We want work that we want to show off and can be proud of.
  • timely - We don’t want to keep coming back to it forever and never finishing it.
  • satisfied client - Our goal is actually to create fans (topic for another article perhaps), so we really want an excited client, but I’ll take satisfied if the other elements for success are there.
  • limited miscommunication - This simply means that the client got what they expected, and we didn’t create or allow unrealistic expectations.  Miscommunication is always going to happen at some point between humans, hence “limited” instead of “no.”

Design first: pros & cons

Pros:

  • The sky’s the limit - You can design whatever you want.
  • Freedom to focus on usability - You need not limit yourself (ex. you need not start from how Views outputs exposed filters by default)
  • Get your client excited with pretty pictures - I don’t know about you, but most of our clients are not very wowed by garland or zen classic when shown concepts.

Cons:

  • The sky’s the limit - You may design something, get the client to approve it, and then chat with your developer or dev team and find it takes forever or is nearly impossible to build.
  • Missing context & use cases - Often, when designing first, there are elements of both content interaction and management that you may forget to consider.  When you develop first you often are in the middle of using and testing which can help you discover all the moving parts.

Develop first: pros & cons

Pros:

  • Save dev time - You tend to more tightly hold yourself to the defaults, limitations, and patterns of the technologies you’re using when you develop first.
  • Avoid unnecessary and painful design revisions - You avoid having to go back to the client to discuss revising the design based on something you figured out you just couldn’t pull off from a development standpoint. This means you also avoid getting your client excited about an idea that you then find can’t make a reality.

Cons:

  • Limit innovation and useability - Let’s face it, there are lots of instances where limiting yourself to drupal’s (or some contrib module’s) defaults or patterns is really NOT the best solution for the problem.
  • Client waits longer to see things they’re excited about - (see pros above for design first)

A third option?

I could probably add to these lists, but I’ll leave it at that for now.  That’s enough for you to see why I’ve said this is a journey and something we’ve not found THE answer to.  One of the things we’ve been trying lately here at Sprocket is to tackle the two congruently.  Where we used to be clearly a design first workflow, we’re now working congruently and allowing the two to inform each other in process.  Obviously if you work alone as a free lancer or have one person who does both for you then that becomes pretty difficult.  So far the congruent approach has at least been more effective I think than our design first approach was.  It can be tricky to figure out client approval processes (I think) without design, but it can be tricky to have the confidence of going to a client for design approval without any attempt at development.  As we flesh out this part of our workflow more here at Sprocket, I or James will try to blog a bit more about it.  I’m anxious to hear from others who have insights or creative ideas for how they structure this workflow with their clients and their projects.

Nov 2009 20

James Sansbury

Avoiding Technical Debt (Part 1)

Some common ways we create it and thoughts on avoidance.

Let’s be honest here… How many times have you told yourself, “Self, don’t forget why you are doing such and such,” only to come back to that same such and such and realize you’ve completely forgotten what you swore you would remember?  Or maybe didn’t even remember that you did it at all? The fact is, our memories are not nearly as sharp as we would like to believe. We need help, and thankfully there are many tools available to the developer to provide that help.

Realize how stupid you really are

Step one in any recovery process is of course to realize that you actually are guilty as charged.  You will only start to change bad habits or create good ones if you start to believe that your life will be better for it.  I’m not normally an advocate of talking negatively to yourself, but to start avoiding technical debt you need to realize that you can’t remember everything, nor should you!  I know you’ve been waiting for this opportunity, so take the time now to tell yourself you’re stupid.  ;)

Compartmentalize

One of the best aids in fighting technical debt before it starts is breaking things out into chunks.  Take views for example.  Have you noticed how many different files and folders there are in that module?  You know what the great thing about that is?  Once you know how it’s architected, it’s pretty easy to find the exact code you are looking for. 

Working on a module? Once your .module file gets to a certain size, start breaking out that code into separate files.  I like to keep all my hook implementations in the .module file, and move everything else out into separate includes. 

Doing Theme integration? Break out your CSS into separate files based on what functionality they are associated with.  Thanks to Drupal’s CSS optimization, you can have as many CSS files as you want, and they’ll all get nicely packaged into one tidy file to reduce the amount of page requests (thereby decreasing load time).

About to commit to a VCS? Avoid making a bunch of separate changes to your code and then committing them in one large commit.  Break them out into chunks based on the fix they are associated with, and make sure to use meaningful commit messages!

Features! One tremendous way we’ve cut back on our technical debt is in creating features.  A feature is a module, so break out your CSS based on features, and use hook_init() and drupal_add_css() to add it to the styles only when the feature is enabled.  Move any hook_form_alter() implementations into the features as well.  Everywhere you can, move any code associated with a particular feature into the feature itself, so that you know exactly where to look when something needs fixing.

On to part 2!

Nov 2009 19

Dwayne Bassett

What are you saying?

Evaluating your message.

We like helping our clients think through their message. Since so much of what we do in planning, designing and developing is for their end user, we want to make sure we fully understand the message our client wants to deliver to that user . The following exercise may only take a few minutes, but you may be surprised at what you might learn through the process.

  1. Consider your service or product and define in very specific terms what you offer.  If you’re a service business, ask “what do we sell?” and not just “what do we do?”
  2. Create a detailed profile of your target audience (ex. age, gender, vocation, income level, education level, hair length, height, weight, ethnicity, whatever you can actually define).
  3. Craft a clear message for your customer.  Make certain it has a singular thought or theme and is not trying to say too many things.

Then ask yourself, “is the message ‘hitting the mark’?”  Whether its through the internet or through print, a consistent and clearly defined message is critical to the success of your service, product, business, etc.