6

Related to: Is onError handler better than exceptions?

Premise

I am writing a piece of library code that performs certain tasks, to separate concerns, we decided it should not write to a log or write to the display directly, but instead provide an event registration mechanism that allows interested client code to listen to events of its life-cycle.

So far so good. We have an event handler for log, and and event handler for display, they are informed when an event occurs and they write to the log / display independently.

So we have so far (pseudo code)

class MyLib(List<MYLibEventHandler> listeners) 

class Display implements MYLibEventHandler

class Log implements MYLibEventHandler

Question

The question that was raised was - how to inform the clients of exceptions? One way of looking at it is that an exception can be looked as just another event. It is something external that happens, and the clients are interested in knowing when it occurs.

So we can simply add another event for exceptions that receives the exception object. (we can re-throw the exception to allow any other try / catch constructs to handle it, but the log / display are not really handling the exception, they are just being notified it happened so they can do whatever they want with it. They can't really recover from it)

On the other hand, it smells wrong. An exception is not a normal event, it's a break in the flow, so we can say that our "main" will catch any exceptions and pass it to the Display and Log instances explicitly, outside of the event dispatch mechanism.

This smells also, because we already have a list of listeners, yet we explicitly call the log and the display to handle the exception.

(Perhaps I should not be alarmed that the code is doing something "exceptional" when handing an "exception". but it still smells that I need to keep track of clients twice)

So I'm stuck with a code smell no matter what I choose.

Is there a design pattern to handle multiple listeners / handlers for the same exception? try catch is very "single listener" / "hierarchical" structure, it doesn't seem the right tool for a wide "dispatch" like scenario. Perhaps some sort of an AOP pattern?

My attempt to answer this is that if I have a remote server, with multiple clients, and the server needs to communicate that a server exception occurred, there would be no question since the client can't really "try / catch" the exception. It will be more likely be sent as an event (e.g. in Akka as a Try object). Even in RMI, the exception is sent more as an "event" and only then triggers a RemoteException locally.

Is there a known design pattern to handle multiple, independent, read-only listeners for an exception (e.g. listeners that can't and won't recover from the exception, they just need to know it happened)

Perhaps in this case, sending the exception as an event (and then rethrowing it) is the right way to go?

2

Error handling is by definition messy. You are basically trying to handle something that shouldn't have happened in a graceful way.

I think the biggest thing that smells is that you are mixing concerns

A developer is concerned with the ability to recreate an error condition and prevent it from happening in the future. Stack traces as close to where the error occurred are a very useful tool for that purpose.

A user is concerned whether the action they took was successful or not. If not they care about whether there is something they can do about it. NOTE: there are more than one way to handle this visually, but the underlying concern is the same.

As a general rule, I prefer to separate those concerns and handle them a bit more appropriately for the end user:

  • If I get an exception, log it immediately. It's useful for debugging.
  • If the exception prevents the user's action from succeeding, raise an event to inform the user that the problem happened in user understandable words.

The bottom line is that users don't want to see stack traces because it doesn't help them. They do want to know if the reason their data didn't get sent was because they did something wrong, or if they just need to try again later. That's why you should always tailor the message you give the user. If it is something that is completely unexpected, then it is better to provide a way to submit error details or reference an ID that can be found in logs on a server than it is to show a raw exception message to the user. They can't really do anything with that.

Bottom line: don't mix error handling with error reporting. And error reporting should be tailored to the appropriate audience.

1

I would think that the clients are not interested in the raising of exceptions, but rather in the handling of those exceptions (an arbitrary number of layers above where the exception was thrown). In some cases they are not even interested in it, for instance if it was handled by retrying and then the operation succeeded.

Once an exception is handled, it becomes business as usual and I therefore think it is appropriate to let interested clients know about this through the regular notification mechanism.

Even if an exception is not handled until it reaches your main function, you'll have to do something to avoid your program getting terminated. Even that is handling the exception and would in my view justify a regular notification.

0

If the clients are listening to the lifecycle of the library, then one sensible lifecycle state would be a "failed" state, which occurs when the library experiences an exception from which it cannot occur. They should be notified by the library code, not from the main function, for the same reason the main function doesn't notify them of any other events.

As @Griffon26 said, if the exception was handled then you may not even need to notify them.

What makes the most sense to me is to not rethrow the exception, but any calls to the library when it has reached the failed state will immediately throw an exception.

I would include the exception object in the notification if you're sure the library will only be used internally because the more information you can provide the better. If it's external then like @Berin Loritsch said the notification needs to be cleaned up and not include the full stack trace and exception object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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