During my recent presentation at LFPUG, Tink was very persistent in suggesting that the event bus used in most MVC frameworks might not be the best solution. This got me thinking about what it would be like to do MVC without an event bus. And so began this little experiment.
You can take away my event bus, but don’t take away my dependency injection.
My project was to create the same podcast application as I used in my various framework examples, but this time without any form of central event bus. Initial thoughts suggested I would need a dependency injection container to maintain loose coupling, so I grabbed my favourite one – SmartyPants-ioc, created by Josh MacDonald.
Using SmartyPants and lots of interfaces I can inject my objects where they’re needed while only creating dependencies on the interfaces not the actual implementations. Thus (hopefully) I can avoid needing an event bus for communication. For example, view mediators (I used the presentation model pattern) have controllers injected into them and call their methods directly. But they only know the interface of the controller, not the actual implementation.
This looks good to start with, but unfortunately I still need events for some things. The obvious example is notification of results from asynchronous service calls, but notification of changes to the model also works well when handled by events. Because I don’t have an event bus, these events will be dispatched by specific objects and must be listened for on those specific objects too.
Does that object dispatch an event or not?
Unfortunately I’m coding to interfaces, and there’s no way to define what events must be dispatched from a class that implements an interface. I could work on trust – assume any object that implements the FeedLoader interface will dispatch a feedLoadComplete event, for example. But if I want my solution to be truly practical, I need something more robust than that.
One of the many nice features of As3-signals, created by Robert Penner, is that the signals are properties of classes so they can be specified in an interface. For this reason I chose to use As3-signals for my events.
For example, the previously mentioned FeedLoader interface defines a getter for the feedLoadCompleteSignal. Now any class that implements this interface must have that getter, and any class injected with an implementation of this interface can trust that that getter will be there, and so listen for the underlying signal.
All in all I think it worked out rather well. There may even be a potential future in an architecture like this. I do fear the explosion of interfaces and injection rules may make the approach unwieldy for a large project, but perhaps multiple DI configuration classes, a clear package structure and disciplined developers is all that’s required. I welcome your opinions on this.
The example is below. Right click on the swf to view the source. Links to the framework versions follow. All versions have identical functionality.
The other versions can be viewed here…