So I am late in getting this posted, but there was a very productive BoF at DrupalCon DC about Handlers that has somewhat changed the intended approach. I will try to summarize what we decided here.
-
The general approach and concept is sound. (yay!)
-
For now we still will not deal with an environment object.
-
Multi-axis routing and pluggable factories introduce too much overhead for the cases where they are not needed. There's a dozen cases where we don't need that extra overhead, and the exact logic needed in the more advanced cases will not always fit into that neat pattern.
-
Instead, we will add explicit support for routing handlers. A routing handler (for lack of a better term) is a facade handler that will get associated to a give target but will itself not actually do anything. Rather, based on additional method calls to it the routing handler will instantiate and make use of other handlers for the same slot, using some mechanism TBD to avoid hard-coding "new" calls.
-
As an example, file handling could have a handler for "local" and a handler for "Amazon S3". If you wanted to use the same storage system for all files, you'd just attach that handler to the "files" slot and be done. If you wanted to route files of certain mimetypes to local and others to S3, you'd attach a routing handler (which could be provided by a contrib module or custom written for your site) to the files slot and then configure it however you wanted to route file operations to the appropriate handler.
-
That means that routing handlers must implement the same interface as the handler for that slot, possibly with other methods as well. That means a RoutingHandlerInterface that extends HandlerInterface.
-
Speaking of configuration, that's a whole other ball of wax. :-) We decided that we needed a built-in, standardized mechanism for handler configuration. We also determined that, just to keep things interesting, there were several levels at which handler configuration could happen: Per-slot, per-handler, and per-attachment/instance. For example, the "caching" slot has configuration (whether to enable certain features in general), the "database" cache handler has configuration (what database connection to use), and the memcache cache handler has configuration that must be done per-attachment (so that page caching uses this memcache bin while block caching uses that memcache bin, despite being the same code). Exciting!
-
We decided that we wanted to use dependency injection for configuration. That is, the constructor of the handler would take the target and whatever its configuration parameters were as arguments, thus ensuring that the handler was always "workable". That mean the configuration definitions and configuration forms must live outside of the handler class itself. Yes, that is different than the way Views 2 works.
-
That puts the definition of options and forms for them into the slot and handler info hooks, which makes sense. That way we know up-front if we need any configuration. Storage of configuration options will be as denormalized as possible for performance reasons.
So that's the basic idea. I figure we need to implement at least a couple core systems with this in order to stress test it. The question is, can we do that in core directly or do we want to do parallel implementations in, say, the handlers module in contrib, in a 3.x branch for D7? And which systems provide the best test cases?
Also an open question... Are there actually configuration options that would be set per-handler, and not per-attachment/handler instance/target? I'm not coming up with any now that I think of it. They'd all make more sense per-attachment.
Anything I'm forgetting? Recommendations on moving forward?

Comments
Test Cases
Awesome run down on the BoF. That pretty much hits all the stuff we talked about I think. So the questions.
No idea on the parallel implementation front. But on the test cases, we got a laundry list of issues watch handlers that we can use to gauge some interest in areas to watch.
Cache is an obvious test case so we should put that right up front. Image toolkits where used to discuss interesting use cases so it'd be a good one too. Also mail is a long messed up system we should keep an eye on. A Longer list from the issue includes session, preprocessing js(css too?), locking framefork, drupal_http_request, and password hashing. I'm certain there are others. Any ideas if any of those are going to contain any tricky problems that would make them good test cases?
The most important task
is convincing Dries.
Personally, it still feels
Personally, it still feels more complicated than I want to deal with but maybe that is because I don't understand all of it.
I don't understand 'routing handler'. The reason for having a 'routing handler' is not explained.
I don't understand why we want a built-in, standardized mechanism for handler configuration. No good reasons are given.
Explanations
1) The routing handler is the replacement for swappable factory functions. Those were removed because everyone objected to the two-stage loading process they required, which had a minimum of two SQL queries. That's how we would do things like mapping files to be stored on different servers based on mime type or size, or multi-layer caching, etc. It's a layer for "you want to do something weird/non-simple? Great, do that here." The advantage over factory functions is that if a given slot doesn't need any fancy handler routing or multiple active implementations (eg, the password hashing system) then it has no unnecessary overhead.
2) A common configuration mechanism is useful because then we don't need to force every handler writer to come up with their own mechanism for configuration. That also allows us to store configuration information along with the routing information in the database (or, yes, in a settings.php override) so that we can pull it all in at once in a single query and instantiate the object with the configuration right there. Same logic as Views storing its own per-plugin configuration in a common way. Potentially it could also allow for a common handler-configuration interface, but I'm not sure yet if that's how we want to implement it. At minimum it would work vaguely like system_settings_form().
Drewish can give more info on the configuration, I believe, since I think he was the one who brought it up. :-)
On the whole it's still a fairly simple system.
More on router handlers
Like Crell said, we had a problem with the handler function routing handler calls. So we end up with the concept of a router handler that proxies requests.
With this design the simple case to just be a basic handler as shown in the first graph on the diagram. Very simple. In the second graph we have a cache router that applies some arbitrary logic and pulls from either a db cache or a memcache. This could allow failback from memcache to the db or any other sort of logic needed.
Since we take advantage of polymorphism the extra logic is in the router and the handler mapping ends up being 1:1 as far as the core code is concerned.
Thought on configuration
So while talking to sdboyer about this the other day, we concluded that rather than having the configuration defaults and a configuration form function and potentially a configuration submit function and so on defined in the slot or handler hook, those should go in a separate configuration class. So if you have a handler that requires configuration, you also declare a MyHandlerConfig class, which implements HandlerConfigurationInterface. If one doesn't exist, you get no configuration or a default NULL object, and there's no extra overhead. If you do need one, then it has form handling methods in it just like views handlers and plugins do. You also get methods to retrieve configuration, check for requirements, etc. Then when a handler object is instantiated, it gets the corresponding configuration object passed into it and can probe it for whatever settings it needs.
That gives us a clean separation between business logic and configuration, lets us keep dependency injection for configuration, allows a place for modules do so all kinds of weird logic in the configuration if they want to (different settings depending on day of week? Who knows?), and somewhat mirrors the way Views works now with form methods. Maximum flexibility with the least number of huge-definition-arrays.
We'd need to decide if slot configuration should be a separate class or a parent class. Are there any slot configuration options people can think of that should be global, and NOT overridden or controlled by the handler/instance?
What do folks think?
Basic switcher class
One possible advantage to this could be that we could provide a basic router handler classes. The configuration class would then contain all the logic for choosing which handler to select and the handler implementer would not have to technically touch a handler class. IE, cache router would basically just be a configuration class using the basic router handler class.
This wouldn't preclude someone from adding arbitrary complexity directly in the handler class but encourage people not to. Seems like a reasonable approach to encourage good designs.
It does seem a bit like arguing semantics especially since we don't have any of that golden code to base our observations on but I'm not opposed to the separation.
Indeed!
It took me a few reads to realize what you were getting at, but yes, that's a very good point. Rather than subclassing for every router handler, you just subclass the configuration object and use one of the provided "common case" routers. That gives us another layer of common cases beyond just the target key, which should simplify implementations while still allowing for "do anything you want for your wacktasktic use case".