Enyo has a pretty deep inheritance heirarcy and one of our areas of research right now is ways to flatten it to improve performance and ease debugging. We’ve discussed increasing our use of mixins (or something similar, perhaps) to add functionality to a kind without defining an entirely new one. Mixins have a couple of drawbacks regarding overriding methods, however:

  1. You have to use kind.inherit which is a bit awkward
  2. It still increases the call stack

One common place for method overrides are the lifecycle methods (e.g. create(), destroy()). In most cases, the mixin does its work either before or after the call to the super without modifying the arguments. To make this a bit easier, I’m proposing a new HookSupport mixin.

How it works

The enyo/HookSupport modules exports the HookSupport mixin allowing a kind to invoke a hook. The module also provides the logic to accumulate the methods attaching to a hook via kind.concatHandler.

Defining a Hook

Hooks are defined at execution time using invokeHook(name, method) where name is a String with the name of the hook (e.g. create) and method is either the name of a method on this or the method itself.

create: function () {
	this.invokeHook('create', this._create);
},
_create: function () {
	// actual work
}

Attaching to a Hook

You can attach to a hook from mixins, subkinds, or instances. You could even attach from the kind that declares the hook though that’s likely not necessary. Each hook supports before and after points to support the common use cases. To attach to a hook, add a hooks block to your kind or mixin with an entry for each point you want to hook.

hooks: {
	beforeCreate: function () {
		// this will run before the 'create' callback
	},
	// this will call this.afterCreateWork() after the `create` callback
	afterCreate: 'afterCreateWork'
}

Notice that hook callbacks do not receive any parameters. Further, return values are ignored. There is no mechanism to stop either future callbacks from being invoked. I could forsee supported either of these scenarios if there were use cases for them.