tags:

views:

245

answers:

5

I have series of functions with different argument signatures:

public void function1 (string s1, string s1, string s3, string s4) {...}
public void function2 (int i1, int i2, string s3, string s4) {...}    
public void function3 (int i1, string s2, int i3, string s4) {...}
.
.
etc //some 30 odd functions

calling each function may throw a set of exceptions like TimeoutException, CommunicationException etc. (yeah these are WCF proxy functions)

Now I have to wrap these calls in try catch blocks but DRY principle says I am doing it wrong by writing so many identical looking try catch blocks:

public void Interfacefunction1 (...) {
    try {
        function1 (...);
    }
    catch (TimeoutException) {
        taskResult.Success = false;
        taskResult.Message = Resources.ServerConnectionBroke;
    }            
    catch (CommunicationException) {
        taskResult.Success = false;
        taskResult.Message = Resources.CommunicationFailed;
    }
}

//and...

public void Interfacefunction2 (...) {
    try {
        function2 (...);
    }
    catch (TimeoutException) {
        taskResult.Success = false;
        taskResult.Message = Resources.ServerConnectionBroke;
    }            
    catch (CommunicationException) {
        taskResult.Success = false;
        taskResult.Message = Resources.CommunicationFailed;
    }
}
//etc

Is there any way write one function which will call these functions and catch exceptions if thrown?

EDIT:

I DO NOT have control on the sequence of interface function in which they will be called. These all functions are exposed to user (another programmer) who will call any one, two or many in any sequence she likes. I just need to report success and error message in case of failure for EACH operation. (please see updated code snippet).

+4  A: 

What happens after you catch the exception? Can you refactor? Often you can, in concept, put the try catch at a different level.

 processUserRequest() {

     try {
           if (function1() )
               function2()

           function3()
           ... etc

           prepare success response to user

     } catch (TimeOutException ) {
           log message
           prepare fail response to user
     } catch ... etc 

     }

     send response

}

Also is it possible to reduce the number of exceptions you need to catch? In Java I tend to use hierarchies of exceptions. I have a TransientException, thrown when its reasonable to expect a retry of the same request to work. Timeout and Communication exceptions are subclasses of TransientException, so I only need to catch TransientrException. Similarly I have an InvalidRequestException - you can make an invalid request as many times as you like but it will never work! So I can then subclass InvalidRequestException for cases such as malformed SQL.

In response to your further explanation:

Your intent is to wrap each function so that the caller can examine a success code instead of catch an exception. The desire is that the caller will code

Response result = function1( ... ) ;
if ( result.isError() ) {
    do something with result.reason();
} else {
    maybe do something with the answer
}

First let me say, why bother? They can catch all Exceptions with one block.

try { 
    function1( ... )
    maybe do somethign with the annswer
}
catch(Exception e) {
    callExceptionReporter(e);
}

this in my eyes is much clearer, the flow of control is explicit. It's no more lines of code and is much more maintainable. There seems to be general opinion that exceptions make code unclear - I just do not agree.

NOTE: The idea of catching Exception has caused some debate. Let me clarify a couple of points.

  1. Catching Exception is not in itself evil, but it is very important that if you do catch Exception you do the right thing. The issues are discussed in this question.

  2. I do not advocate silenty swallowing any exception, least of all important system exceptions. For each caught exception one needs to decide whether to log a message, often logging is the minumum correct thing to do. In the case under consideration we are catching Exception so that we can factor the common processing. It's not the usual thing to do, but catching that Exception is not intrinsically wrong, providing that we do the right thing. Do not blindly follow rules such as "do not catch Exception".

  3. The implementation of callExceptionReporter() has responsibility for doing the right thing. For the application-specific exceptions can prepare the error result. For the other exceptions it can simpy rethrow.

  4. Certain exceptions are not catchable. Example From .Net 2.0 StackOverflowException is not (usually) catchable. This makes no difference to our code, we don't catch it, we don't want to catch it.

  5. There have been suggestions that by catching Exception we may open up some possibility of finally blocks misbehaving. This is simply not the case. Finally blocks fire long before our Exception handler is reached. If finallys misbehave it's not dues to the use of this catch. If we reach this catch because a finally block threw an exception, no matter its just another exception to process or rethrow.

Returning to your original question If you want/need to go ahead with your plan, then as has been observed, factor the actual Exception processing to its own function. You are then writing minimal repeated code.

try { 
    return function1( ... )
}
catch(Exception e) {
    return prepareExceptionResponse(e);
}

So long as you do the right thing in prepareExceptionResponse(), rethrowing low level exceptions you are not doing any harm. It's unusual to cathc Exception at this level but you have a special need - to do some common exception processing.

djna
Thanks for the tip of catching generic exception. Please can you see the updated question and respond?
Hemant
In response to your updated answer: Catching all types of exception is a BAD thing in my book.
Hemant
I'm doing that because I didn't want to assume that your functionN() functions use a particular hierarchy. I would prefer to catch MyAppsException. However catching need not be bad, you are at liberty to code callExceptionReporter() to rethrow exceptions that you don't want to catch.
djna
@djna - until .NET 4.0, it's very bad to catch `Exception`. It means you catch various low-level fatal errors and so disguise bugs. It also means that in the event of some kind of corruption that triggers such an exception, any open `finally` blocks on the stack will be executed, so even if the `callExceptionReporter` fuunction tries to log and quit, it may not even get to that point (the `finally` blocks may throw again, or cause more corruption, or delete something important from the disk or database).
Daniel Earwicker
@Earwicker - very intersting. So interesting that I'll open another question. I'd appreciate your comments there. I will come back and edit this answer should I achieve elightenment :-)
djna
I have opened http://stackoverflow.com/questions/1298289/net-and-c-exceptions-what-is-it-reasonable-to-catch this question
djna
@Earwicker I am amending my answer to address the points that I think you intended to make. Consensus on the other question is that my Adding that catch Exception exposes no new dangers relating to finally blocks.
djna
+1  A: 

You're going to have to call each function and catch the exception each time. But, you could make your code cleaner if you used something like the Exception Handling Block in Enterprise Library. That way, you could set up a policy for a failed WCF call and not have to handle each different type of exception individually.

JP Alioto
A: 

Have a class that handles all the possible exception that can occur in your application. Expose a method from that class which will handle the exception. The method can take in the exception type, where it occured etc. kind of arguments and handle them accordingly.

In the series of methods you have, just call the method in your exception handling class.

danish
Please can you see updated question and respond with example?
Hemant
+8  A: 

You could use lambdas:

CatchCommonExceptions(() => function1(...));

private void CatchCommonExceptions(Action action)
{
    try
    {
        action ();
    }
    catch (TimeoutException) {
        taskResult.Success = false;
        taskResult.Message = Resources.ServerConnectionBroke;
    }
    catch (CommunicationException)
    {
        taskResult.Success = false;
        taskResult.Message = Resources.CommunicationFailed;
    }
}

And you can have a Func<T> overload for those that return values.

EDIT: You can view complete source here.

Richard Szalay
+1 if you would add the actual action() call in the try block :-)
jeroenh
+1 also if you fix that.
Daniel Earwicker
What's the scope of that taskResult variable? Is it declared in the enclosing class but visible to the lamba?
djna
I've used this exact layout for things before. Works great.
280Z28
It wasn't specified in the original post so I assumed it was class level. If it is local, it could be passed into CatchCommonExceptions
Richard Szalay
@Richard: I took the liberty to link the the full source I derived from the answer. I hope you are OK with it.
Hemant
+1 this is a really interesting answer. Thanks very much, and thanks for clarifying the scope question.
djna
A: 

Have not verified by myself, yet, I just came up with the following:

try {
function1 (...);

}
catch (Exception ex) {
    //this will not catch all the exception types even though it may look like :)
    HandlingWCFExceptions(ex, taskResult);
}
....
private void HandlingWCFExceptions(Exception ex, TaskResult result)
{
    try {
        //This will preserve the original exception status including call stack
        throw;
    } 
    catch (TimeoutException) {
    taskResult.Success = false;
    taskResult.Message = Resources.ServerConnectionBroke;
    }         
    catch (CommunicationException) {
        taskResult.Success = false;
        taskResult.Message = Resources.CommunicationFailed;
    }
    //catch other (WCF) exception types that you can handle safely
    //Any other exception not caught here will bubble up
    ...
}

This one will work nicely with any funtionN() with different arguments and return types, especially when you do not have any control on WCF services.

Chansik Im
It removes the duplicate catch blocks to SOME extent but not completely. Can you suggest something better? (NOTE: I am not the one who down voted you.)
Hemant