Seriously have you ever tried it? In my last post, I talked about dependency injection and the final portion of that article was about how I used it in my latest project. I explained that I’m using a central application object as an event hub, but rather than objects referencing it directly, I was injecting it via constructors. Well, here I’ll be talking a little bit more about how I’m using that event hub and probably very little about dependency injection.
For the new Minecraft server manager, I decided to try out Marionette, which extends Backbone to offer some new functionality and eliminate a lot of boilerplate code (especially from views). I’ll be doing an extensive series on it some other time, but for right now I’ll just point out a few minor components, particularly Application and EventAggregator.
Marionette introduces Application, which is an object that is designed to be the central hub of a Backbone application which implements a module system and many other nice pieces. I only use the EventAggregator that is built into it as the
vent property. The EventAggregator is essentially just an advanced form of Event from Backbone.
Application.vent as the location where all of my modules communicate with one another. This isn’t the only means of communication between components, but, if it can help make something more reusable, then I try to use this instead of directly coupling objects. I’ll talk about this more later.
Since our event hub is attached to a piece of the application that is known throughout the system, we can broadcast messages to nearly any part of the system. I feel like the biggest challenge with this is choosing which events to emit and naming them.
This can be pretty simple. Just choose the events that you know something else in the system will need to respond to. But this means that when you expand the system, you might need to add more events in. Personally I try to think ahead to see if there are any events that something else might want to use in the future. This is this part that can be a bit difficult, but for anyone who wishes to extend the system, it’ll have been worth it. You can consider these events as “hooks” for others to plugin their own functionality into without having to modify much, if any, of the existing code base.
The naming is only difficult if you actually care, which you should. Consistency in names is extremely important for code readability, and system-wide event names are just as important, if not more important, than naming a property or method of an object.
Why not show you an example or two of what I’m talking about? In the Minecraft server manager, I use WebSockets to communicate between the server and clients about things that are happening with the Minecraft servers. I have a single module that handles these communications with the back end.
If a client asks for a Minecraft server to start running, then the back end will alert all of the clients that the server is running. The above object will receive that notification and use the event hub to let the rest of the world know. Another component listens for this event and adds the new running server to a collection that specifically holds the running servers. This component then triggers an event that lets the system know that a server is started. The tab manager hears about this event and creates a new tab for that server.
You just heard about several components that all communicated with one another but not a single one of them had any clue the other existed. Their communication was based entirely on events controlled by the event hub. You can completely remove pieces of this system and there will be no errors (but also very little functionality) because there are no dependencies, except on the event hub, which is injected, so you can use any event system that has an
trigger method. If the event system you want to install doesn’t have this interface, you can always create an adapter.
Though traditionally, you may not be exposed to events as a way to architect an entire system, they work quite well, especially in persistent client-side applications. On the server side with technologies such as Java or PHP where the “application” handles a single request and then dies, it doesn’t work too well, but if you’re using something like Node.js where the application is constantly running and waiting for responses, it can work out pretty well. If it makes sense for an application, try it and see if you like it. You might be surprised at how nicely it works. God bless and happy coding.