Ben Nadel recently wrote about an experiment with event propagation (http://www.bennadel.com/blog/2037-Simple-Publication-And-Subscription-Functionality-Pub-Sub-With-jQuery.htm). In his post, Ben talks about preventing event propagation. That is, if agents A, B, and C are listening for event "customerAdded", it seems to make sense that, say, A could encounter a situation in which it would want to stop B and C from responding to the event. Makes sense, no? Well, no. But to explain, we need to delve into the world of parallel universes...
Although the idea is initially appealing, there are two problems with it.
The real power of event programming lies in the ability of any and all agents to listen for a particular event. Imagine the following situation: you have an application that has been written, tested, and running. One day, your boss comes up to you and says, "Say, I've been talking with our Customer Service folks and they think what would really take this app to the next level [bosses seem to love cliches] would be an online context-sensitive help system. That can't be too hard, right? Can I have that, say , next Friday? Great..."
In fact, in a quirk of fate , at the same time that your boss is telling you that, in a parallel universe, another boss is telling another you the same thing. Only, in that parallel universe, you created an eventful web application. Let's compare the two yous.
You here: "Great? Yeah, really great. Now, I have to basically rewrite large parts of the app. And by next Friday? They really need to stop passing out crack to management..."
You there: "Great? Great! Now, I'm really glad that I wrote an eventful application. Adding a help system will be as easy as writing a module that listens for key events. And by next Friday? No problem. I should be able to finish this up within four days, then I'll be free to continue reading up on this crazy idea of parallel universes. I'm really glad we have such a crack management team."
So, how does the you that's there plan to do this so easily? And how do events help him...err...you?
Let's listen in as you talk to the Customer Service folks.
You: I understand we want to implement a context-sensitive help system?
Customer Service: Yes. We get a lot of calls from users that we think could be avoided if there were some simple help available.
You: OK. And there are specific areas where we want to provide help?
Customer Service: Yes, things like adding a customer. There are four parts to that process. We get the same questions over and over -- so much so that we've written a script that we use when users call.
You: Perfect. What I'd like you to do is create a spreadsheet with two columns: Column A will have the action users take that you want to provide help with. Column B will be what you'd like them to see. That sound doable?
Customer Service: Sure! We can basically use the scripts we've already written. Only...do you know that the boss wants this done by next Friday?
You: Shouldn't be a problem -- provided you can get me that spreadsheet soon?
Customer Service: I'll have it to you tomorrow.
Me: Wow, I'm impressed with how you handled that. You should be too. But how -- exactly -- are events going to help you?
You: Well, it works like this: when a user wants to do something -- take the example of creating a new customer -- we announce an event.
Me: What's an event, exactly?
You: Maybe an example will be the best way to give you a sense of that. Take the upcoming rally that Senator Hilton is speaking at.
Me: Senator Hilton? As in "Paris Hilton"?
You: Of course! That's an event, right?
Me: Yeah...that would be some event.
You: Huh? Anyway, the event has a name, "Rally To Restore Decency", and it has other things associated with it: location, date, etc.
Me: You don't mind if I sit down? My head hurts...
You: Oh, sure. So, in the computer world, we also have events and they have things associated with them.
Me: Can you give me an example?
You: Let's take the case where someone wants to create a customer. The name of that event might be "CreateCustomerRequest". And there are things associated with that event.
Me: Like the customer's name, address -- stuff like that?
You: That will come a little later. For now, it should include things like where on the page we're going to display the form to get that information. And the user that wants to create a new customer -- so we can make sure s/he has permission to create a customer.
Me: Ah, I begin to see.
You: Now, the system is already announcing that event. My help system just needs to listen for "CreateCustomerRequest". When it hears that event being announced, it can respond by putting the Customer Service script in a div on the page. The only thing that will really need to change is that I'll need to add a div to insert the help instructions.
Me: Oh, I see! That is cool.
Now, back to the idea of preventing event propagation -- preventing, in other words, other listeners from hearing that event. That fundamentally breaks the entire purpose of events.
You: You know, if you really needed to do have one agent prevent other agents from responding, you should choose the "Chain of Responsibility" pattern -- that would fit that situation better.
Me: Good point! Say, are you from here...or there?
Me: Paris Hilton, senator or socialite?
You: What?? She's a socialite.
You. Whew. OK.
Back to our discussion. So, the first objection to the idea of preventing event propagation is, we might say, philosophical: it misunderstands the nature and purpose of events. But the second objection is practical.
If something like "CreateCustomerRequest" is announced and A, B, and C are listening for it, they are typically doing so by providing a callback that someone -- let's call it an event broker -- will use to notify them of the event.
Now, if A wanted to prevent propagation, there's no guarantee that his command to prevent event propagation would happen before B and C responded. So, the very idea of stopping event propagation just doesn't work.
You: There's a better way to handle that. I was just discussing that the other day with my fellow developer, Ozzy.
Me: Ozzy...as in Osborne?
You: You know him? What a smart guy. But he really needs to lighten up. I swear, the guy does nothing but work, work, work. Anyway, if A should be able to prevent anything else from happening...
Me: Can you give me an example?
You: Ok, well, let's say that the user has a license to create up to 100 customers. Before, I do anything like display the form, I might fire an event like "CreateCustomerPermissionRequest". Now, A listens to that and, if the user still has open customer slots, A can announce "CreateCustomerRequest".
Me: And if the user doesn't have permission?
You: Then A would announce "CreateCustomerRequestDenied".
Me: And who would listen for that?
You: That's just the point: we don't know or care! Maybe no one is. But in the future? Who knows?
Me: So, that's how you use events to sort of "future-proof" your code.
You: Right. But, hey, I've got to run. I have to interview a candidate for a graphics position. Let's see...somebody named "Hal Helms". Hey, are you OK? You don't look so good...