views:

189

answers:

9

I find myself having a lot of this in different methods in my code:

try
{
  runABunchOfMethods();
}
catch (Exception ex)
{
  logger.Log(ex);
}

What about creating this:

public static class Executor
{

    private static ILogger logger;

    public delegate void ExecuteThis();

    static Executor()
    {
        // logger = ...GetLoggerFromIoC();
    }

    public static void Execute<T>(ExecuteThis executeThis)
        where T : Exception
    {
        try
        {
            executeThis();
        }
        catch (T ex)
        {
            // Some kind of Exception Handling Strategy...
            logger.Log(ex);
            // throw;
        }
    }

}

And just using it like this:

private void RunSomething()
{
  Method1(someClassVar);
  Method2(someOtherClassVar);
}

...

Executor.Execute<ApplicationException>(RunSomething);

Are there any downsides to this approach? (You could add Executor-methods and delegates when you want a finally and use generics for the type of Exeception you want to catch...)

Edit: Sorry for being unclear - what I was really after was some input on the general idea of trying to move the execution of code from the class in question to a more generalized class that does this. I just did a quick mock-up of a solution but in real life you would naturally use things such as exception handling strategies, abstract execution base classes with more specialized execution classes for a specific layer/part of the system. I generally create one method with the try.../runABunchOfMethods-part (this does the exception handling, with specialized exceptions) that calls the runABunchOfMethods that in turn execute a limited set of other methods "clean code" style.

I'll buy the obfuscation argument on some levels but if the whole solution/architecture takes this proposed approach a new programmer should be able to understand the pattern.

I've edited the Executor to include a generic T to allow the calling code to specify the exeception just to show how to handle a specialized exeception. In other cases you might have a bunch of catch:es depending on the what you want to do but those are special cases in the concrete subclasses I was talking about.

+1  A: 

The downside would be a lack of flexibility. What if you wanted to recover from a specific exception in one of the methods being called - e.g. on a failed connection to an SMTP server you may want to store the contents of an outbound mail in your database for retry later? This the reason why you should avoid catching the general Exception type whenever possible.

Also, you lose some of the clarity of your code (in my opinion, anyway) as it is hard to see where exception handling happens.

ZombieSheep
+11  A: 

The downsite is your approach of general exception handling. You should not catch the baseclass Exception without a strong reason. It could hide various problems; ok, you log them, but your code doesn't know that it just ran out of memory, or the file does not exist and continue as if there was no problem at all.
The method you describe here would encourage a general exception handling.

Related:
Is it really that bad to catch a general exception?
Is this a bad practice to catch a non-specific exception such as System.Exception? Why?

EDIT (response to the OP's edit & clarification):
I am not sure what you want to achieve. Basicall you hide an exception (general or specified - it is just swallowed). Call your method Executor.Hide<ApplicationException>( RunSomething ); and it is clear what happens here. But is there any advantage in swallowing exceptions? I don't think so. Again, there can be places where you need this - but they are rare and should be chosen intentionally. The method you provide encourages to swallow exception without thinking about it.
You commented out the rethrow line (throw ex or better just throw, which preserves the stack). What do you get with this line enabled? Basically just logging. You catch an exception, log it and rethrow it to ... catch it again? Why can't you put your logging to this latter place?
Try to catch an exception only, when you are able to handle it. There you can log, too. Any good logger will be able to show you the stack trace, so that you have no loss of information.

Related:
Where to put try catch?

tanascius
+1 if i could, i would upvote more than once.
Jehof
I've edited the code to use generics and pass in a T : exception to show that you could easily specify a specialized exception. Please see my edit.
antirysm
@antirysm: I updated my answer ...
tanascius
"Why can't you put your logging to this latter place?" - I tend to use different logging strategies injected through IoC based on the layer in scope (most errors get logged to the db but what if the db server is down? - then I "log to" SMTP - ie send a mail). A layer should be able to handle some types of exceptions without having them bubble up to the UI.
antirysm
+2  A: 

You get another level of indirection which might make your code harder to read and understand (especially for someone looking at your code for the first time).

ho1
I'm not so sure, code with a bunch of exception handling in-line is not that easy to read. And in this case it's a fairly intuitive pattern that's being presented.
John
+1  A: 

If you're seeing that code in a lot of classes then you are doing something very very wrong in my book :-) At the very least you should re-throw the exception (with just "throw", not "throw(ex)"), but the whole idea of catching the base exception all the time just to log it (or indeed at any time, bar a few edge cases) is not the right approach for me.

I have no idea what kind of application you're writing, but can you not hook events such as AppDomain.UnhandledException, which fires whenever there's an unhandled exception (one that you haven't caught) in any thread, and log those? You might want to combine that with more specific catch statements that also log, if you want to log recoverable exceptions too.

Steven Robbins
Yup, the Exeception ex was just an illustration (albeit a bad one). We're talking about methods at a very low level where just a limited number of exceptions are in scope.
antirysm
+1  A: 

I'll jump on the "it makes you likely to misuse exceptions by only catching at a general level" bandwagon. However you might benefit from some sort of 'exception handling delegate wrapper' in more specialized cases. For instance if you were doing lots of work with DB-related classes that always throw the same exceptions, you could have a dedicated DB-exception-wrapper.

Ultimately though, the fact that exceptions'clutter' your code is the downside to making your code safe.

John
+1 Thanks for understanding the intent of my question! :) Please see my edit!
antirysm
+1  A: 

You don't really win anything, but you lose some things:

  • Readability
  • Simplicity (you introduce another class, another delegate that a reader must understand)
  • You can't simply step over the Executor.Execute to get to Method1(...). If you step over, you skip the whole code block in your delegate.
  • ...
chiccodoro
+1 for the debugging point - that's a really valid concern! Thanks!
antirysm
A: 

At the very begining....

You should NOT have a code like below scattered around in your code base.

try 
{ 
  runABunchOfMethods(); 
} 
catch (Exception ex) 
{ 
  logger.Log(ex); 
} 

I would suggest you should first look at the actual need of a code like this. You should be catching a very specific exception in all the cases ( unlike a generic catch all).

After that, if you still still multiple methods catching same exception then you can think of creating multiple methods in your executor which handle a specific exception type.

Amby
I should have been more clear; the code above will be the only code in a function; the runABunchOfMethods() will contain calls to limited set of other functions. "Clean Code"/Uncle Bob-style...
antirysm
A: 

Normally the best pattern for logging exceptions in your application is to only catch exceptions at the top-level methods in your code.

  • In a console application you should catch and log exceptions in Main.
  • In a WinForms application you should catch and log exceptions in your event handlers.
  • In a service you should catch and log exceptions then the ThreadProcs of your worker threads.
  • Etc.

At almost all other points in your application you should only catch specific exceptions and then rethrow a new exception wrapping the original exception. If you don't need to wrap the original exception you don't need to catch the original exception in the first place.

Sructuring your application like this will lead to only a few places where you catch, log and "swallow" exceptions.

Martin Liversage
Yup, I've edited the question to try to explain my intent a bit better. My concern is that I want to keep my "real" objects as clean as possible. In my example I used Logging as an examples but I'm thinking of different aspects too (such as auditing, tracing etc) which I would prefer not to clutter my normal code. I find that much of the pattern is the same so I would like to reuse it in a more generalized way while still allowing for specialization.
antirysm
+2  A: 

If you want to keep your objects clean, you could consider using an AOP framework like PostSharp. Then your logging of exceptions (for example) can all be handled in one place if you so desire.

EDIT:

It is possible to remove the try / catch blocks using postsharp - here is an example common exception handler that could be created in PostSharp:

[Serializable]
public class CommonExceptionHandling : OnExceptionAspect
{
    public override void OnException(MethodExecutionEventArgs eventArgs)
    {
        // can do some logging here
        // ...

        // throw the exception (out of postsharp) to where it occurred:
        eventArgs.FlowBehavior = FlowBehavior.RethrowException;                       

        // If you want to ignore the exception, you can do this:
        //eventArgs.FlowBehavior = FlowBehavior.Return;

        base.OnException(eventArgs);
    }
}

If you apply this attribute to a class, any exceptions that any methods in that class throw will then be directed through the above code.

David_001
Nice! That was precisely what I was looking for - and using attributes on your methods is much nicer than the Executer.Execute(delegate)-stuff. Looks like I wasn't that far from the answer as everyone thought... :) Anyone know of any other AOP Frameworks that support AOP-style Exception Handling? (For comparison...)
antirysm