[development] RFC: info hook standardization

David Strauss david at fourkitchens.com
Mon May 19 14:20:43 UTC 2008

Great proposal.

One addition: a way to invalidate the cache of an info hook if your info hook does something like reading from a database table. This would be the case if, say, your module generates a configurable set of ad blocks.

-----Original Message-----
From: Larry Garfield <larry at garfieldtech.com>

Date: Mon, 19 May 2008 00:15:11 
To:development at drupal.org
Subject: [development] RFC: info hook standardization

Unlike the IETF, I am actually looking for comments and feedback at this
point. :-)

In recent versions, Drupal has developed an increasing number of
registry-style hooks.  By "registry style", I mean a hook that serves to
build a ginormous (technical term) associative array and return it, and does
nothing else.  hook_menu(), hook_theme(), hook_node_info(), those are just a
few of such hooks.  CCK has one for formatters and another for widgets.
Views has hook_views_default_views() and, in Views 2, a couple of others as
well.  There's an issue[1] to convert hook_blocks() over to that format, too,
for a variety of reasons.

In most cases, these hooks are called rarely and then cached, either in the
cache table or in a dedicated table such as menu_router, or they aren't but
easily could be and probably should be.  However, it is not always readily
apparent which is the case.  For instance, hook_forms() is not a registry
hook in that it is contextual, and cannot be cached that way in its current
implementation.  (Perhaps it should be, but that's not what I'm getting at.)
Some such hooks have a corresponding _alter hook, others do not.

I therefore am going to propose a conventional standard for such
registry-style hooks.  I will dub them "info hooks", because about half of
such hooks currently end in _info() already.  An info hook would be defined
as follows:

- It has a name of the form hook_$singularNoun_info().
- It takes no parameters.
- It returns a nested associative array of arbitrary complexity
- it has a corresponding _alter hook (vis, hook_$singularNoun_info_alter()).
- It is structured in such a way that its results can and are cached (either
in the cache table or a dedicated table, depending on the use case).
- That cache is permanent, so under normal operation the hook never needs to
be called again.
- The new registry system knows to never pre-load the file in which an info
hook resides, or rather to never flag a file included for an info hook for
pre-caching.  (We don't want to inadvertently flush the cache and then
trigger a rebuild of those hooks on a node view page, because then we end up
loading thousands of unnecessary lines.)

Thus, any hook that ends in _info() you can reliably know exhibits those
properties (and possibly others), and a hook that does not end in _info()
does not exhibit all of those properties (although it may certainly exhibit
some of them, c.f. hook_form_alter()).

This has a number of advantages:

- Clarity.  Right now, when you see a hook you don't know inherently if it's
cached or not, if it has an alter hook, etc.  This way, you know that if it
ends in _info(), it either does all of the above or it's a bug.

- Consistency.  Consistent APIs are good APIs.

- Ease of development.  When developing a new hook, a developer can say to
himself "Ah, this is starting to look like an info hook, which means I don't
need to guess what features I should add; I should just go ahead and make a
full info hook out of it."  You never know when that alter hook will be
useful to someone. :-)

- Encourages declarative programming.  Eh?  Declarative programming in PHP?
Just so!  Declarative programming is harder to make obscure, stupid bugs in
(assuming you know the syntax), because most bugs are either syntax errors or
blatantly obvious.  Yes there are exceptions (some of the more complex SQL
queries I've written come to mind), but in general you're less likely to get
subtle bugs with an associative array.

- Encourages generic engines.  A generic engine that relies on declarative
input is flexible, because you can then program it via a declarative syntax.
Solving the generic problem may be more difficult in the short term, but in
the long-term it buys you a great deal of flexibility.

- Easier to document.  Drupal's APIs are admittedly sometimes wacky and
obscure.  By separating the engine from the declarative interface to it, we
can put a lot of power into the hands of hook authors with a very simple,
easy to document syntax.  We also have a clearly documented behavior for how
an info hook is supposed to behave.  Parameter orders also then are not a
problem, since array key orders don't matter.  The array keys also then serve
as a form of self-documentation.

- Backward compatibility.  Yes, the unholy words!  Just like one of the
advantages of XML is that you can arbitrarily add new tags and existing
well-written code won't automatically choke, you can add new keys to an
associative array and as long as there is a sane default, existing code
doesn't have to change unless it needs to.

- Less executable code.  The key goal of the Drupal 7 code registry is to load
less code.  Well, if we move more power into tightly written engines that are
controlled by run-once hooks that we no longer need to load, that's less
code, and more less code the more modules you have.  Take every module's
hook_menu, hook_theme, hook_node_info, hook_views_default_views, hook_block,
etc. and simply remove them from the common case.  Good bye several thousand
lines of code.

Naturally not everything can or should be a registry hook, and we shouldn't
try to shoe-horn Drupal into being just an array-processor.  However, this is
a trend I have observed in Drupal development that it would behoove us to
embrace and standardize and (dare I say!) extend the use of.


Implementing this plan would involve documenting it, of course.  We would then
rename hook_theme() to hook_theme_info(), hook_menu() to hook_menu_info(),
etc.  At that point we could investigate other subsystems that it would make
sense to turn into info hooks.  I suspect we will find a couple besides the
block system(hook_block_info() anyone)?  In the process, we may discover
places where "obvious" flexibility is missing.

Excuse me while I go get my flame-retardant suit.

[1] http://drupal.org/node/257032

Larry Garfield			AIM: LOLG42
larry at garfieldtech.com		ICQ: 6817012

"If nature has made any one thing less susceptible than all others of
exclusive property, it is the action of the thinking power called an idea,
which an individual may exclusively possess as long as he keeps it to
himself; but the moment it is divulged, it forces itself into the possession
of every one, and the receiver cannot dispossess himself of it."  -- Thomas

More information about the development mailing list