Braindump on the Event Aggregator Pattern

I’m working up my chapter on the “Event Aggregator” pattern for my book this evening and I’m starting by collecting my thoughts on the subject.  If you feel like you have to comment and give me free advice for this chapter, then I guess you should do that (please).  I’ve written about the pattern before here and here.  I’m also referencing some other patterns that I haven’t written much about yet.  Ward Bell and John Papa have both blogged on these patterns.  I’ll blog about my StoryTeller implementation tomorrow night.

In case you’re new to the pattern, the Event Aggregator object will:

Channel events from multiple objects into a single object to simplify registration for clients.

In essence, it’s a specialized form of the GoF Mediator pattern.  It’s a “hub” object in your application that you can use to do decoupled “publish/subscribe” messaging between different parts of your application.  I’ve used the pattern with WinForms apps, WPF with StoryTeller, and even JavaScript in web pages (going to be very important as we implement a dashboard pattern for our web app at work).

 

Here’s my braindump on the pattern:

  1. Registration.  Somebody has to be responsible for registering the listeners with the event aggregator hub. 
    1. You could have the listeners themselves do the registration by taking a dependency on the event aggregator as is idiomatic with Prism.  This is great because it makes it obvious when looking at a class whether or not it is registered as a listener.  I’m not a fan of this approach because I think it’s awkward and adds repetitive code to each listener – and repetitive code should be stamped out wherever it pops up.
    2. You could use another object like a “Screen Activator” (more on this pattern later) to do the registration of ViewModels/Presenters, screens, or non-UI elements as listeners.  This has the advantage of removing the responsibility of bootstrapping away from the class (ViewModel/Presenter/service) that does the real work. 
    3. This is really just 2a, but you could use a custom “Registry” class to make the explicit subscriber subscriptions in one place.  I like
    4. Use conventional registration with an IoC tool to automatically add objects to the event aggregator as appropriate.  I use a marker interface plus a StructureMap “interceptor” to do this in StoryTeller.  This is the “easiest” mechanically, but adds some overhead to understanding how the pieces connect.  But, and there’s a big but, conventions are black magic rather than explicit code.   
  2. Discoverability/Traceability.  An event aggregator is a form of indirection, and indirection almost always makes a system a little harder to understand.  At some point you definitely need to understand what objects are publishing and which are receiving events.  Strong typed events are a boon here because it’s relatively easy to use advanced IDE features like R#’s “Find Usages” to quickly determine publishers and subscribers to a particular type of event.  The event aggregator analogue in CAB depended on string keys and made troubleshooting harder.  Event aggregator implementations in JavaScript and other dynamic languages will have the same issue.
  3. Diagnostics.  For those of us using static typed languages, you might want to add a diagnostic report that can be generated on demand that can scan the codebase and identify publishers and subscribers based on a dependency on the event aggregator.  Using marker interfaces or common super types for message classes can make the diagnostics much easier.
  4. Event Filtering.  Simply put, not every subscriber cares about every instance of a type of event.  For example, StoryTeller has several widgets that need to respond to every single test event (queued, executing, finished), but the individual test screens only respond to events involving their one particular test.  In this case you need to worry about how events are filtered.  The responsibility for the filtering can be in:
    1. The listener itself.  The listener knows what it cares about, so let it decide whether or not to continue processing the event.
    2. Filter within the EventAggregator itself.  You can either register the listeners with a subject like this:  EventAggregator.Register(this, myTest), but this is assuming a specialized event aggregator that “knows” about the subject.  Another way is to make the registration with a Predicate or Func<T, bool> to filter within the event aggregator.  I’m still experimenting here inside StoryTeller with this pattern a little bit.
    3. I’m thinking about having either an IoC interceptor or a Screen Activator do the filtered event registration.  Again, the point is to move the grunt work of setting up the screen out of the ViewModel/Presenter to keep the ViewModel/Presenter relatively clean
  5. Thread Marshalling.  It’s very handy to just let the event aggregator take care of marshalling callbacks to the screen back to the UI thread.  The Prism Event Aggregator gives you fine grained control over whether or not the marshalling should take place.  Maximum control might be nice when every bit of performance matters, but then again, it makes you error prone in a part of the code that is hard to test.
  6. Queuing. At this point I let the StoryTeller EventAggregator just process things synchronously, but running the event publishing on a background thread or queuing events up may be necessary to conserve resources.
  7. Open/Closed Principal.  Using the Event Aggregator makes it much, much easier to add new features to your system without modifying existing code as you would have to if you were dependent upon direct communication without an event aggregator.  This is an important issue for teams doing incremental delivery or cases where multiple teams are working on the same system in parallel.
  8. Garbage Collection:  Your event aggregator has to keep a reference to all the subscribers.  This can present you with some serious memory leak issues as screens are closed, but not garbage collected if the event aggregator is keeping a reference.  You can beat the issue by using WeakReferences internally inside your event aggregator.  The other option is to explicitly un-register listeners.  The WeakReference strategy may be more reliable, but has its own issues.  Explicit un-registration isn’t that bad if you are using a “Screen Conductor” to manage the screen activation lifecycle.  Much more on that later…
  9. Event Latching.  Two issues here:
    1. It might be valuable to ignore events at times.  I’m specifically thinking about the case of a screen on a tab that is not active/displayed.  Let’s say that this screen receives an event about financial market data being updated.  The act of updating the hidden screen’s display turns out to be very expensive in terms of resources.  You might want to quietly ignore or “latch” events when a screen is deactivated and hidden.  That of course adds some complexity to make the hidden screen “know” to update itself when it is activated again.  I think this is where the “Screen Activator” and “Screen Conductor” patterns come into play.  If there’s a standard workflow that happens whenever a user activates a tab, then the “screen activator” should get an Activate() call.
    2. In some specialized cases you may want the Event Aggregator to “latch” itself while in the midst of responding to an event.  This is especially important when a widget responding to an event publishes other events.  Think about “change” events getting published during the act of binding a screen to new data.  In this case the event aggregator should ignore new events until the first is completely finished.
  10. Event Ordering.  It might be important that events be completely processed in the order that they arrive to the event aggregator.  For example, Chad & I had an issue last year with a subscriber receiving an event, then publishing other events that were processed before the original event reached all of its subscribers.  There might be a code smell in there somewhere, but event ordering may be something you need to consider.
  11. One size does not fit all:  It can often be advantageous to have multiple event aggregators within one application.  I often find it useful to use an event aggregator that is scoped within a single complex “Composite View” when a single screen is very complicated within its own right.
  12. Instrumentation.  The EventAggregator is effectively a message bus and has all the same advantages as a message bus.  Sending all events through the event aggregator gives you a great centralized place to put instrumentation code.  Less repetitive code == fewer mistakes and better productivity.

 

What about the Prism EventAggregator?

Many people first come into contact with the Event Aggregator pattern through the implementation in Prism.  For my regular readers you may be shocked (shocked I say!) to know that I don’t particularly care for the way they implemented the pattern in Prism.  I think the Prism implementation is clumsy and awkward to use.  I despise that idiom of first getting the event aggregator, then retrieving an “Event” object that I’ll then listen to.  Same thing with publishing.  I think it’s awkward that I have two steps (get event, then publish) instead of just saying “IEventAggregator.Send().”  All of that is unnecessary noise code, and the “get event, then listen/publish” adds a little bit of overhead to every single unit test that I write that involves either listening to or sending events (more mock object setup, and that would add up more than the extra production code).  No, that’s not a huge deal, but noise code adds up, and every bit of ceremony/noise code I can remove due to infrastructure will make me more productive and the code easier to deal with by making it easier to read.

All I want is to go:

  1. IEventAggregator.Send( the message ).  Nothing else.
  2. The listeners should have little or preferably NO/ZILCH/NADA coupling to the event aggregator.

I think Prism is far better than CAB, but it’s still headed for some of the same problems that CAB had.  The complexity and awkwardness of the EventAggregator in Prism is directly caused by trying to make the EventAggregator generalized to every possible scenario that you can think of.  You will be able to create a better implementation of EventAggregator for your application by tailoring something simpler for only the things you need.  At a minimum, you could at least put an application specific wrapper around Prism’s generalized API’s to make them easier to consume.  I think you could stand to sacrifice some of the flexibility of the Prism EventAggregator and end up with a simpler to consume alternative.

Don’t take this as a specific criticism of Prism itself, because the real issue is that generalized application frameworks are an automatic compromise.  The single most important reason that Prism is better than CAB is that you could easily, and I do mean easily, roll your own Event Aggregator and replace the one in Prism while still using the rest of Prism.  Hooray for “Composition over Inheritance.”  You couldn’t do that with CAB.

 

Wiki:

God willing and the river don’t rise, I will have a public Wiki up for the Presentation Patterns book by the end of the weekend.  On advice from multiple people, I’ll be writing most of the first draft on the public Wiki.  I’ll announce it as soon as it exists.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Presentation Patterns. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Tuomas Hietanen

    How about using Reactive Extensions (and RxJS) as Event Aggregator?

  • http://codebetter.com/members/jmiller/default.aspx Jeremy D. Miller

    @vgupta,

    http://codebetter.com/blogs/jeremy.miller/archive/2008/02/15/build-your-own-cab-18-the-command-executor.aspx

    You could do it cleaner today w/ Lambda’s.

    Sorry, but I’m going to maintain my StackOverflow virginity and leave it alone.

  • http://codebetter.com/members/vgupta/default.aspx vgupta

    Hi Jeremy,

    I had an implementation for Threading class using EventAggregator. Can you please share your comments for
    http://stackoverflow.com/questions/2190178/can-prism-eventaggregator-be-used-for-threading-needs

    I am not sure if this is misuse of EventAggregator or we can use it this way too.

    thanks for your time.
    Vishal

  • http://blog.galasoft.ch Laurent Bugnion

    I published V2 beta of my Messenger (part of the MVVM Light Toolkit) that I think answers some of these concerns/features. It was developed with a lot of inputs from Glenn Block, and we tried to correct some of the anoying things from Prism’s EA that you mention here.

    http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx

    One thing I am still hesitating to integrate is the automatic dispatching of messages to the UI thread. I see how that can be useful. So far, I am a bit wary of this, though, because I feel that multithreading is too complex to hide it (even though I understand the intention). For the moment, I prefer to have the code that dispatches the messages visible. Also, it is kind of hard to implement a consistent interface that works the same in Silverlight and in WPF (this is not a concern for many, but it is for me). Anyway, this might come in a further version if I find a good way to do it.

    Thanks for the interesting post.

    Cheers,
    Laurent

  • http://dotdotnet.blogspot.com/ Ido Ran

    I think there is something missing. The reason I think the publish and subscription are two step operations is because in Prism implementation the event has the brain, not the EventAggregator.
    All the aggregator really do it act like a IoC or just plain old singleton container for the event instances.
    Currently there is only one concrete implementation of IEvent but you can have as many as you need – and the logic of subscribing to event can be unique to each type of event – things like thread marshaling, sync/async publishing, cancelable events – that’s why I think they didn’t put Register and Publish methods on the IEventAggregator interface.

    Another thing is that since Prism is already based around the concept of Ioc (Unity most of the time but not always) we can use the IoC to be the repository of the events and thus remove the need for IEventAggregator all-together.

    Thank you for the post,
    Ido.

  • http://uglylispcode.wordpress.com joseph gutierrez

    One other thing that may be missing is an multi-event listener? Can this be done in filtering maybe?

  • http://uglylispcode.wordpress.com joseph gutierrez

    Here is a working sample of mapper(presenter first).

    http://www.box.net/shared/lfvr4vpy6h

    Right now I’m getting the feeling that maybe using a mapper may be overkill. Maybe going to closure.

    If you want to discuss further. my e-mail is: gutzofter@yahoo.com

  • http://uglylispcode.wordpress.com joseph gutierrez

    @Jeremy,

    My Bad! You are right it is nothing like a mapper. After going through StoryTeller I found that ExecutionQueue holds a reference to the aggregator. Sorry for the confusion.

    I do have a question.

    Why dont you have the events decorate with a mapper(presenter first)? It seems to me that the events generated in ExecutionQueue is an added responsibility to running tests. Lets say we want to change the events or the sequences of events then we have to change ExecutionQueue. Or if we want to use ExecutionQueue but we don’t want to use events?

    Can you give a post concerning the testing tool MockFor that is used to test EventAggregator? This seems to be a kick ass little tool!

  • http://codebetter.com/members/jmiller/default.aspx Jeremy D. Miller

    @Joseph,

    I’m not following you. How is this anything like a Mapper?

  • http://uglylispcode.wordpress.com joseph gutierrez

    I think you should use a mapper pattern instead of a mediator pattern to describe the essential idea behind the aggregator. Another thing is maybe this is more inline with a framework.

  • John Hatton

    @Benny,
    I’ve been trying out this approach and it’s good so far. I register the event class with the container, then add it to the constructors of the publisher and subscribers.

    Jeremy, is this what you’re refering to when you write:

    >You could have the listeners themselves do the registration by taking a dependency on the event aggregator as is idiomatic with Prism. This is great because it makes it obvious when looking at a class whether or not it is registered as a listener. I’m not a fan of this approach because I think it’s awkward and adds repetitive code to each listener – and repetitive code should be stamped out wherever it pops up.

    If so, are you saying Jeremy that the line in the ctor which says

    fooEvent.Subscribe(e=>HandleFoo(e.Details));

    is the repetitive part you don”t like?

    I love the simplicity so far, but I’ve also wondering how well this will scale… I don’t want to end up with some ctor with half a dozen event parameters.

  • http://wizardsofsmart.net/ Ryan Riley

    You mentioned that the Event Aggregator pattern is basically a message bus, but I thought it was more of a message broker. What’s the difference, if any?

  • http://twitter.com/VirtueMe Benny Thomas

    I don’t understand why we need to send round the IEventAggregator, shouldn’t a class just tell in it’s constructor or be setters that they need a eventclass like the want a service or repository?

    Then they could subscribe or publish this event as they like? I really don’t need the complexity the EventAggregator adds to the playground!

    A event is a specialized object to communicate between different objects. It should be designed for one purpose and one purpose only.

    Let structureMap serve the event to objects as it builds them up. A event is a singelton as I know it.

    It may not add some value to the discussion, but this is the only way I see we can get rid of the unwanted complexity a EventAggregator adds. Why do we not want to make things simplified?

  • Ike Casteleyn

    Hi,

    I’m looking forward to the book.

    If I could add one extra topic.
    I think you name it as “types” of events, but could you also explain how to handle/register events with different parameters (different number, different types)

    Not that I think you need it, but here’s also a link from someone who created “weakevents” that might be informative.
    http://www.codeproject.com/KB/cs/WeakEvents.aspx

    Best regards,
    Ike

  • http://www.chrisholmesonline.com Chris

    On a recent project I worked on, I used the event aggregator pattern you wrote about in your BYOC series. I get what you’re saying in regards to registration feeling awkward, but I have to say, I really like that way of handling events. It’s so explicit. Easy to test as well.

  • http://blogs.claritycon.com/blogs/sean_devlin/default.aspx Sean Devlin

    Great post, Jeremy. A little while ago, I made something like an event aggregator or mediator in JavaScript. More info here: http://blogs.claritycon.com/blogs/sean_devlin/archive/2009/06/23/a-lightweight-event-framework-in-javascript.aspx

    I’m afraid mine was a little simplistic and naive, but I think it worked well enough for my use cases. I think some of the big pain points in mine are discoverability and garbage collection.

    The latter wasn’t a big problem in my app, since everything was built around the assumption that you subscribe once and then never again. But that’s not immediately clear from looking at the usage, so it could be trouble.

    Anyway, lots of good points and food for thought.

  • John Watson

    For the record, the whitespace only appears in Google Reader’s view of the blog entry. Clicking through to the actual blog site looks okay.

  • http://kentb.blogspot.com Kent Boogaart

    (huge amount of whitespace after your post when viewing your blog in FF)

    I have similar sentiment towards the Prism EventAggregator. I kind of get why it is designed like it is, but it adds unnecessary complexity to my code. Therefore, I also have come up with my own solution. I blogged a bit about it here: http://kentb.blogspot.com/2008/03/event-hub.html

    On the subject of diagnostics, I think it’s also very useful to have a runtime picture into who is connected to what. A VS debug visualizer that lists all known events and their handlers, for example.

  • Ward Bell

    Loved the post. All that white-space at the bottom has got to go though :-)

    Started a reply concentrating on the Prism EA problems … and it just got out of hand.

    Rather than polute your blog, I decided to stain my own, Here’s where to find it: http://neverindoubtnet.blogspot.com/2009/07/simplify-prism-event-aggregator.html

    I think I’ve “solved” your most salient objection regarding the Prism EA 2-step. Getting rid of subscriptions remains an open matter.