[development] Eliminate hooks entirely in Drupal 6

Earl Miles merlin at logrus.com
Tue Jan 23 22:21:25 UTC 2007

After some discussion this morning, I am putting up a proposal to eliminate 
hooks entirely (though not the concept of hooks) and replace them with 
officially registered callbacks. I have identified several areas where this 
will improve Drupal (primarily in terms of probable performance gains). There 
are 2 parts to this.

Part 1: drupal_register_callback

   function drupal_register_callback($callback, $function = NULL, $file = NULL)

This function is only called from a particular location; ideally in its own 
separate .register file that only needs to be loaded when the callback registry 
is being rebuilt. However, it could also be a function within the .module file. 
There are some questions here, primarily balancing ease of use for the 
developer versus performance for the system. When it is called, the system 
should already know which module context is being used.

This function would register a given callback (examples: nodeapi, form_alter, 
etc) with the Drupal system. The registry would replace the logic 
module_implements uses to determine which module implements which hook.

The $function would be what's called. In today's world the function would be 
called mymodule_nodeapi; and it would likely not change, but we should allow 
registration to specify the function used. If left blank, the default function 
name would be constructed. (i.e, modulename_hookname).

The $file would be a file that should live in the same directory as the .module 
file and tells the system which file to conditionally load when that callback 
is invoked. This is one of the things that creates a big advantage in this 
system: We could move callbacks into conditionally loaded files, allowing 
Drupal's minimum per-page codesize to be smaller. The 'nodeapi' hook is not run 
for every page load, but because hooks are anonymous right now, that code 
*must* be present. When you can conditionally load, however, the required size 
of the .module becomes very small. (in fact you would only keep items in that 
file that are called on every or nearly every page load. Currently that's 
hook_init and hook_menu but with changes to hook_menu that one may well be 
eliminated from every-page-load calls, and the .module file itself may not even 
need to be loaded for every page).

Invoking a callback would still be the same:
   module_invoke('callback', arguments...);

Part 2:
   function drupal_register_theme($theme, $args, $function = NULL, $file = NULL)

This works very similarly to callbacks, but it registers a theming function 
that can be overridden by the theme. The only difference in is the $args 
argument, which is an array that tells the function how to translate function 
arguments into the $vars array, for use in .tpl.php files.

For example, let's say I have the following theme function:

function theme_foo($node, $bar, $baz);

The $args array would be: array('node', 'bar', 'baz').

Themes would also have a similar registry; we may need to make it slightly more 
complex so that it could work with the theme engine to automatically register a 
template. Which means we might want to find a way to make it simpler for 
themers to register the templates they're using (for example, a directory scan 
could find well-named template files and automatically register them based upon 
already known registered info).

This entire system (callbacks and functions) would be cached, so information 
would only need to be re-read when modules and theme settings are updated. A 
'development' mode might be necessary that re-reads this information every page 
load. There would probably be some way for devel.module to expose this setting 
and automatically disable development mode when devel.module is enabled.

Overall benefits to this system:

1) Some execution time is saved looking up module hooks. I don't believe this 
is a great deal of execution time, but it is definitely some.

2) A great deal of code can be loaded conditionally, reducing Drupal's 
footprint. I believe this could be a *very* significant boost to Drupal and 
could vastly reduce the amount of code that is loaded, making Drupal far, far 
friendlier to hosts that cannot use an opcode cache.

3) Certain namespace collisions will be avoided. Developers will no longer be 
penalized for forgetting that mymodule_user() is the user hook.

4) Theme functions will no longer have to hunt around for their function; they 
will not have to test the file-system to see if templates exist. They will know 
exactly where to go when the time is right.

5) Theme template files will be easier to include in modules. In fact, if 
implemented properly, modules could actually include .tpl.php files, make the 
proper registration, and no theme code will be harmed by being in the .module 
file *at all*.

6) phptemplate.engine can have much of its code removed to core, making it 
easier to implement alternative template engines.

7) As an interesting side effect, themes could be made to implement 
hook_form_alter, if we coded it that way. There is a value to this, and also an 
argument why this might not be a good thing.

Overall cons:

1) Having to register a callback is less convenient than simply naming a 
function. It's even more inconvenient to have a .register file. However, using 
the existing naming convention, the module_builder.module *could* be made to 
scan a module and produce a .register file or a register function.

2) Having to register theme functions is similarly inconvenient but I think 
it's no worse than we have now.

3) Having to reregister upon making changes is very inconvenient; a development 
mode would be a must.


More information about the development mailing list