5

This is more of a design question and i was hoping to get pros and opinions on what makes sense.

BACKGROUND

Imagine something that holds one or more event listeners. Every now and then the thing fires events to its listeners.

PROBLEM

The problem is of course that listeners that follow after a listener that throws never get to know about the event. THis means that the order of listeners thus is an issue.

SOLUTION #1

Execute all listeners catching any thrown exceptions. This means all listeners are fired but in itself introduce other problems.

What should be done with caught exceptions ?

  • One option is to catch them all and after firing all events throw another exception which holds all the problems. ++
  • The other option is to log ~~
  • The last is to simply ignore these exceptions. --
  • Listeners are executed in isolation which is good. ++

SOLUTION #2

This option is the simplist and simply lets any thrown exception from a listener escape, resulting in remaining listeners never getting fired. Problems with this approach mean that

  • the order of listeners is significant(-)
  • simple to implement(+).
  • before listeners can affect the caller

Q

Which approach makes sense and causes the least number of problems. Does it really make sense to isolate listeners so they get events but cannot cause a running operation to abort if they throw ?

2 Answers 2

7

A couple of points to consider:

Listeners should be well-behaved in as much that they protect their own code's execution from letting exceptions escape to the outside.

The event firer (?), that is the one firing the event, has (should have) no interest in whatever the listeners do with it. Its only job is to ensure that all listeners get to hear about the event. This means that it should protect against one of the listeners doing anything that would prevent other listeners from getting the event. So, yes, catch exceptions.

The event firer has no interest in catching exceptions other than to ensure that bad behaviour by one listener doesn't affect other listeners. So in this case "eating" the exception could be argued for. However, eating exceptions doesn't help anybody, so logging the exception with as much detail about the offending listener as possible is the way to go.

I wouldn't have the firer collect exceptions and finally raise one of its own accord. Quite simply because the firer did its job correctly and has no need to throw an exception. By logging the exceptions thrown by badly behaving listeners, the firer is already doing its part in aiding any debugging needed. (Logs should always be free of exceptions...).

4
  • 1
    Are there any real cases where it makes sense that a listener can "abort" the current process which is why it threw the ex in the first place ?
    – mP01
    Sep 12, 2011 at 12:49
  • @mP01: No, not to my mind. A listener should not have that kind of power of whatever it listens to. And if it does need that power, throwing an exception from an event handler is not the way to abort any process it is listening to. Sep 12, 2011 at 12:56
  • Sorry i hate the terms observable and observer as they share too many similar letters and at a glance for me open for error. I prefer to terms for both ends that are very different and not merely different by some suffix. Thnx for the last thought.
    – mP01
    Sep 17, 2011 at 10:53
  • @mP01: Uh, where did I use those terms? Sep 17, 2011 at 14:43
1

Usually the event source (observable) is decoupled from observers. So the design is something as below :

Observable -> (fires)-> Observer1,Observer2,Observer3...ObserverN

However if you need to add extra logic add one more indirection using an ObserserProcessor class.

Observable -> (fires)
           |->ObserverProcessor1-->(log each)--> Observer1 ... Observer9
           |->ObserverProcessor2-->(whatever)-->Observer10 ... Observer20

This way your logic of observers are still decoupled from observable class but grouped nicely so that you can still add extra processing logic in the middle.

I hope this helps.

4
  • 1
    You have completely ignored the prblem of what to do with exceptions that are thrown by observers.
    – mP01
    Sep 12, 2011 at 12:51
  • You did not actually recommend which approach to take. The q is not about >how< to solve the problem its more of >waht< makes sense most of the time.
    – mP01
    Sep 13, 2011 at 22:08
  • 1
    Look at Enterprise Integration Patterns eaipatterns.com There you will see many patterns used for messaging. I suggested something like Process Manager to you. eaipatterns.com/ProcessManager.html The manager would be responsible from handling exceptions from observers or handling any other expected/unexpected behavior from observers. So in the end you have one more indirection between observable and actual observer and this solution seems OK to me. Check out the patterns in more detail as most of them can also be applied to software modules, use the most appropriate one.
    – O.C.
    Sep 14, 2011 at 6:05
  • I was hoping for a simpler answer rather than introducing another abstraction. By introducing a PM the question then becomes, do i create impls for each of the possible strategies and which should be the default.
    – mP01
    Sep 15, 2011 at 11:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.