17 September 2011

Why you don't like Rules (and why you're wrong)

Shy Carrot

In the Drupal community, openly disliking a module is quite rare. Even when commenting on the lower and of the crappy and abandoned modules, developers usually say "I'd use module X instead". When it comes to the Rules module, however, I have several times heard people saying things like "I don't like Rules" or "I think Rules is a bad idea".

Just to be on the same page: Rules is a module for "event-condition-action" procedures on Drupal sites. In other words, when a selected event occurs on your site, Rules can check a number of conditions and – if appropriate – execute a number of actions. "When a user logs in, redirect to front page if the user isn't administrator." "When comments are posted, send an e-mail to the site editor." You got it. (If not, have a look at these screencasts.)

There is no question that event-condition-action is a useful model for making things happen on your site. This is why Drupal has so many hooks, allowing programmers to add extra functionality here and there in the Drupal execution cycle. So why the skepticism towards Rules?

In my experience, it is normally coders who don't like Rules. (This hypothesis is supported by the fact that Rules is among the top 2% of Drupal 7 modules.) The reasons against Rules generally falls into one or several of these categories:

  1. It is easier to write your own hooks.
  2. You have more control over your own hooks than Rules plugins.
  3. It is better not to rely on other modules if you don't have to.
  4. Rules is overly complex, and is thus by default a bad framework to rely on.
  5. Rules is a heavy, and is thus by default a bad framework to rely on.

With the possible exception of the first reason, I think all of these are wrong. In short, this is why:

  1. Rules integration is easy
  2. Rules integration doesn't imply Rules dependence
  3. A framework for event-condition-action would help a lot of modules
  4. Rules provides good practices to learn from

Rules integration is easy and non-intrusive

It is not a surprise that you can add a Views handler to your module without making it depend on Views. Nor that you can write autocreation functions for your fields without depending on Devel Generate. Also, not surprisingly, your modules doesn't have to depend on Rules to integrate with it.

If you provided a hook_rules_action_info telling Rules about your action function, then you would allow the 50–60K sites using Rules to utilize your functions in a more flexible way. It doesn't have to be more complex than this: "My action function is called my_callback, and takes a user object and a text string as arguments". Declaring events and conditions follow similar, simple (and well-documentented) forms.

Let's have a quick look at some benefits you – and the people using your modules – may get from making events, conditions and actions known to Rules:

  • Your actions and conditions may be used from other parts of Drupal (such as Views Bulk Operations or Page manager).
  • Your actions and conditions may be combined with those provided by other modules, to create more complex effects.
  • The input data for your actions may be modified before being sent off. No need to run an extra drupal_alter.
  • More actions can be added to the events fired by your modules. No need to run your own module_invoke_all and force other modules to implement a special hook.

What is the cost? You can still call your function directly. Rules is not made a dependency for your module. The cost is 20 lines of code.

Yes, it is still quicker to just write the hook function you need, and not bother with Rules compatibility. At least in the short run. To me it sounds like defining node types by code. It sounds like writing SQL queries instead of using Views. It sounds like "I like writing my own code and I'm not interested learning and collaborating on others' frameworks". It doesn't sound very Drupal to me.

Rules unifies functionality

If you are concerned about Rules being heavy and possibly being a performance killer – I share your concerns. I have yet to find (or do) a performance study on what happens if you run Rules on every page load. But I am also concerned what happens if you have many modules being called individually on each page load. Rules provides a nice wrapper for other modules to dive into – which means that they can all be skipped in one go.

Here's an example: The Context module probably has a smaller footprint than Rules. But if your site also uses Path redirect, Page title and Custom breadcrumbs, I wouldn't be surprised if the modules in combination have a significantly larger performance impact than Rules. And Rules could be used to do most if not all of what those modules do. Right now. Really. (And it caches stuff for you.)

If those, and other modules had their events, conditions and actions run through Rules, I think it would be possible to save quite a bit of performance. And even if we lost a little performance, we would gain an immense amount of flexibility.

The alternative is having same type of code being written over and over again, and modules with similar functionality not being able to talk to each other. Not very fun.

Rules provides good practices to learn from

What I'm saying so far is that you can use Rules to do what your modules are already doing. But there are also new things to learn from Rules.

The Drupal 7 version of Rules has a data management layer that could be very useful in other parts of Drupal. The data management builds on information provided by Entity API, but also extends it with a number of non-entity data types.

In Rules, every piece of configuration in knows how the data can fit together. If an event provides a text string it can be used for config input expecting text strings – but not dates or durations. All configuration expects a certain type of input, which (as far as I know) makes Rules the module that has gone farthest in managing data and configuration in a clean way.

There are other practices to learn from Rules as well:

  • Rules are exportable and works well with Features.
  • Rules export code is easy to read for human eyes.
  • Rules has a good SimpleTest coverage.
  • Rules has clean APIs and good developer documentation.

In my experience there are not many modules – even among the top 100 – that are as good on following best practices as Rules is.

What does not make sense

Rules is a complex framework. To some extent it is heavy. But it is a fact that event-condition-action style modules are pretty common – and it doesn't make sense NOT to have a framework for them. Rules may not be the perfect tool, but it a good tool and it can be improved.

Developing events, conditions and actions as if Rules didn't exist is ignorant. Not taking time to learn about important frameworks is not ok – nor to reinvent sub-parts of Rules over and over again. Knowing how Rules work, and then chosing not to use it, is ok.