views:

1373

answers:

6

Ever since Microsoft has introduced the application blocks, I've been bumping into people who use the Exception Handling Application Block. I've recently had a closer look myself and would summarize the basic functionality as follows (skip the following block if you already know what it does):

The exception handling application block aims to centralize and make fully configurable with config files the following key exception handling tasks:

  • Logging an Exception
  • Replacing an Exception
  • Wrapping an Exception
  • Propagating an Exception
  • etc.

The library does that by having you modify your try catch blocks as follows:

try
{
  // Run code.
}
catch(DataAccessException ex)
{
    bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Policy");
    if (rethrow)
    {
        throw;
    }
}

Based on what is specified in the app.config for the policy name (see here for docs), HandleException will either ...

  • throw a completely new exception (replace the original exception)
  • wrap the original exception in a new one and throw that
  • swallow the exception (i.e. do nothing)
  • have you rethrow the original exception

Additionally you can also configure it to do more stuff beforehand (e.g. log the exception).

Now here's my problem: I completely fail to see how it can be beneficial to make it configurable whether an exception is replaced, wrapped, swallowed or rethrown. In my experience, this decision must be made at the time you write the code because you'll typically have to change the surrounding or calling code when you change the exception handling behavior.

For example, your code will likely start to behave incorrectly when you reconfigure such that a particular exception thrown at a particular point is now swallowed instead of rethrown (there might be code after the catch block that must not be executed when the exception occurs). The same goes for all other possible changes in exception handling (e.g. replace -> rethrow, swallow -> wrap).

So, to me the bottom line is that the exception handling block solves problems that really don't exist in practice. The exception logging and notifying bit is fine, but isn't all the other stuff just a perfect example for overengineering?

A: 

Quite simply: if you want different exception handling in your release code than in your debug code, then it would be useful.

Mark Brittingham
Do you have a real-world example for that? Do you rethrow a particular exception in debug mode, but swallow it in release?
Andreas Huber
I kept searching for these real-world examples to prove its usefulness, but unsuccessfully so far.
Marcel Gheorghita
+7  A: 

If you use exceptions for control flow, then you would want to stay away from policy-based exception handling.

But in the case of exceptions which you want to treat as non-recoverable (a background task failed, the socket was disconnected, the file was deleted, etc.), you may want to have configurable, policy-based exception handling.

For example, if you are developing an API, you may want to have every function in your API throw only the standard exceptions (ArgumentException, etc.), as well as your own library-specific exception in the case of an inner non-standard exception (e.g. a MyLibraryException). In this type of case, all that matters is that something did not work correctly. You are not picking apart the exception and figuring out what went wrong. You are simply acknowledging the fact that something went wrong, and that you are supposed to do something now.

That something should be configurable, because it doesn't really matter what you do. Display a Message Box to the user? Modal or non-modal? Log the exception? How do you want to log the exception? Call a logging web service? Append to a log file? Write to the Windows Event Log? Insert an entry into the database? Insert an entry into two databases? It doesn't really matter to the rest of your application. The choice of how to handle an exception is completely orthogonal to the rest of the application.

(As an aside, this is not how I would approach configurable policy-based exception-handling. I would tends more towards an AOP style, such as registering an exception-logger interceptor in the container.)

Justice
I agree that you might want to configure what will happen (notify user, log exception, send email to support, etc.) before your application goes down anyway. You seem to refer to all the rest (swallow, rethrow, etc.) with "control flow", right?
Andreas Huber
Not necessarily - it depends on the software. If you are treating exceptions as recoverable, then you are treating them as control flow. If you are treating them as non-recoverable, then you might be interested in this application block.
Justice
Treating an exception as recoverable would be something sending an Update statement to SQL Server if a corresponding Insert statement failed. That's control flow.
Justice
You usually can't really avoid treating at least some exceptions as recoverable, right? One example is the System.IO.FileStream constructor, which can throw a number of exceptions that most applications would want to recover from.
Andreas Huber
The task at hand may be unrecoverable. The application as a whole may want to recover, and may want to inform the user that the task at hand failed, and ask the user if he wants to retry that task. The context of the particular task, the exception is non-recoverable; for the app, it is recoverable.
Justice
Following this logic, every thrown exception is unrecoverable first (because it almost always aborts an operation in progress) and maybe later becomes recoverable (namely when you catch it somewhere up the call stack and decide that you can do something about it), correct?
Andreas Huber
That is correct.
Justice
A: 

In my opinion, one real value of using the Exception Handling block begins with the one line of code in your catch block:

bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Policy");

One line of code -- how simple can you get? Behind the one line of code, the policy, as it is configured, makes assignment/updates to a policy are easily carried out, all without having to recompile source code.

As was mentioned, the exception policy can actually perform many actions -- whatever is defined in your policy. Hiding complexity behind the one line of code as shown within the catch block, is where I see real value.

I would say complex, but not overengineered. So my thoughts are that big dividends will be seen during maintenance when you're needing to change the way you're handling/logging exceptions by having the flexibility to change configuration easily, and still have the same one line of source code.

Don
Ok, but have you ever seen the need to only **only** change exception propagation (This particular exception was rethrown in the past, let's wrap it in a different exception and throw that in the future) and leave all surrounding code unchanged?
Andreas Huber
+3  A: 

I run into this problem when I am developing functions that have no recoverable state. I believe this policy driven exception handling is actually useful and ensures that all the other developers that are part of this project actually adhere to a standard for non-recoverable exceptions.

I agree with the posters above, you may want to stay away from policy based exceptions if you are using them for control flow.

Signal9
+1  A: 

I don't think this is over engineering at all. in fact. the fact that exceptions can pass through a central handler has been a good thing in my line of work. i have had developers who would eat every exception - handled or not so that it would not bubble to the top and put something alarming in front of the end user or seriously mess up a service/daemon when uncaught.

now with the policy we can start logging at any time without having to restart or needlessly sprinkle logging logic throughout the app. now we can watch exceptions and the like all without taking the app offline.

smart programming if you ask me...

MikeJ
Regarding the developers eating exceptions: Wouldn't it be a much better idea to inspect their code with code analysis tools (e.g. FxCop) to ensure that they don't just swallow everything?
Andreas Huber
A: 

I have to agree with the statement that "the exception handling block solves problems that really don't exist in practice." I've used the block since its release and I rarely feel like I'm actually gaining much by using it. Well, perhaps a bit of a headache. :)

Before starting, I will admit that I do like the Exception Shielding at WCF Service Boundaries functionality. However, that was added fairly recently, involves no coding -- only attributes and configuration, and is not how the block is usually sold. This is how Microsoft shows it at http://msdn.microsoft.com/en-us/library/cc309250.aspx

alt text

To my eyes the above is flow control.

try
{
  // Run code.
}
catch(DataAccessException ex)
{
    bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Policy");
    if (rethrow)
    {
        throw;
    }
}

When you combine the flow control aspect with the code above you are definitely not making wrong code look wrong. (Never mind that the if (rethrow) construct does not offer very much abstraction.) This can make maintenance more difficult for developers unfamiliar with the policy definitions. If the postHandlingAction in the configuration file is changed (it will probably happen at some point) you will probably find the application behaving in unexpected ways that have never been tested.

Perhaps I wouldn't find it as objectionable if the block did not handle flow control but simply allowed you to chain handlers together.

But perhaps not. I don't actually recall ever being asked to:

  • add a new piece of functionality when handling an exception (e.g. in addition to logging to the event log also send an email. Actually, the logging block can do that on its own if you were already logging the exception yourself. :) )
  • change the exception handling behavior (swallow, rethrow, or throw new) across an entire "policy".

I'm not saying that it doesn't happen (I'm sure someone has a story!); I just feel that the Exception Handling Application Block makes programs harder to understand and maintain and this usually outweighs the functionality provided by the block.

Tuzo