Must never do Antipatterns – Exception Handling

By wakao

From java.net: Exception-Handling Antipatterns

Antipatterns
Log and Throw

Example:

catch (NoSuchMethodException e) {
LOG.error(“Blah”, e);
throw e;
}

or

catch (NoSuchMethodException e) {
LOG.error(“Blah”, e);
throw new MyServiceException(“Blah”, e);
}

or

catch (NoSuchMethodException e) {
e.printStackTrace();
throw new MyServiceException(“Blah”, e);
}

All of the above examples are equally wrong. This is one of the most annoying error-handling antipatterns. Either log the exception, or throw it, but never do both. Logging and throwing results in multiple log messages for a single problem in the code, and makes life hell for the support engineer who is trying to dig through the logs.

I see this in so many “commercial” products that I want my money back !!; makes debugging a pain the neck. Seeing the same trace logged from every tier again & again is not pretty.

7 Responses to “Must never do Antipatterns – Exception Handling”

  1. Mike Says:

    having been on the pointy end of such things, no, it’s not wrong, at least not as a sweeping generalization. IFF the language run-time make sufficient stack tracebacks available in the post-mortem, and those can be correlated accurately with the logs, then yes, the logging need not be quiet so paranoid.

    however, in a system where exceptions can pop from deep inside multiple places, i’d much rather have the undwinding trace there in one place. back in the good ol’ days of batch computing with *card decks* and *printer listing*, this is precisely the approach we’d take on big codes because you had to make as certain as possible that what came out before the crash was sufficient to diagnose and repair the code without another run. this is particularly important for large computation jobs that run for hours before blowing apart.

    so while there is certainly grounds for moderation in logging every twitch that happens, there is also great wisdom in making sure that acquiring the one missing piece of information you need to diagnose the problem doesn’t require recreating conditions which may be expensive or impossible to reproduce. you can always ignore log information – it is very difficult to use information that is not there.

  2. Jason Holbrook Says:

    When you are throwing exceptions back through a service call you can’t get the detail on the caller side of what happened underneath. You have to log and throw.

  3. Gene Says:

    I don’t think the author understands Java exceptions or logging well. Or perhaps he was overgeneralizing for effect.

    Throwing an exception does not necessarily cause output.
    Printing a stack trace does not necessarily write to the log.
    Sometimes an exception must be thrown even though it will be gracefully dealt with higher in the stack, but you still want to log that it happened (and where it happened).

  4. Ricky Clarkson Says:

    I’d rather use a callback to handle exceptions.

    Instead of


    void method() throws IOException
    {
    new FileStuff().write();
    }

    I’d have:

    void method(SideEffect ioExceptionHandler)
    {
    try
    {
    new FileStuff().write();
    }
    catch (IOException exception)
    {
    ioExceptionHandler.run(exception);
    }
    }

    interface SideEffect[T]
    {
    void run(T input);
    }

    Then they can be chained fairly easily, and you don’t feel the need to deal with exceptions before you need to. It also gets away from the ugly try..catch in client code – generally a client will satisfy a method parameter requirement better than they will handle an exception.

  5. mv Says:

    The original post characterizing ‘log and throw’ as an antipattern is mostly correct in the large: the fundamental problem with the exception syntax in languages like java and c# is the pathological use of the exception construct for domain logic handling. Thus the ‘log and throw’ approach doesn’t address the underlying issue, which is poor design.

    Alas, many common api’s and vendor api’s now use the exception syntax where better decompostion and error reporting would be cleaner, more maintainable, more portable, more extensible, and just plain more correct. So what’s a poor developer to do?

    Wrap the pathological exceptions. Design layered services which appropriately abstract implementation details at each level and report results (including ‘error’ cases) in the semantics of the usage domain, not the implementation details. Thus the reply about needing the trace detail is a bit off base. One can always log stuff anyway, if needed.

    As a programming technique, Ricky Clarkson’s approach: using a callback is one of the better approaches that I’ve seen. Kudos.

    But the fundamental issue is still design, design, design.

  6. anjan bacchu Says:

    hi there,

    In case you want to chain exception and then only print/log exceptions at the higher layer, I noticed that if you use the XML Formatter(in java), the cause exception (the source of the exception) is not printed. Only if you use the Simple Formatter, the cause exception stack trace is printed.

    don’t know why, though?

    BR,
    ~A

  7. Web 2.0 Announcer Says:

    Must never do Antipatterns – Exception Handling

    [...]This is one of the most annoying error-handling antipatterns. Either log the exception, or throw it, but never do both.[...]

Leave a Reply