Design Pattern for Error Handling - c#

I've ran into this problem a few times on various projects, and I've wondered if there's a better solution than the one I normally end up using.
Say we have a series of methods that need to execute, and we want to know if something goes wrong within one of the methods and break out gracefully (potentially undo-ing any previous changes...), I typically do the following (pseudo C# because it's what I'm most familiar with):
private bool SomeMethod()
{
bool success = true;
string errorMessage = null;
success = TestPartA(ref errorMessage);
if (success)
{
success = TestPartB(ref errorMessage);
}
if (success)
{
success = TestPartC(ref errorMessage);
}
if (success)
{
success = TestPartD(ref errorMessage);
}
//... some further tests: display the error message somehow, then:
return success;
}
private bool TestPartA(ref string errorMessage)
{
// Do some testing...
if (somethingBadHappens)
{
errorMessage = "The error that happens";
return false;
}
return true;
}
I just wondered (and this is my question) if there's a better methodology for coping with this kind of thing. I seem to end up writing a lot of if statements for something that seems like it should be slicker.
I've been suggested having a loop over a set of delegate functions, but I'd be worried that would be over-engineering the solution, unless there's a clean way to do it.

I think you should probably be using exceptions. Note you should generally only be catching exceptions at the "top level" in your application.
private void TopLevelMethod()
{
try
{
SomeMethod();
}
catch (Exception ex)
{
// Log/report exception/display to user etc.
}
}
private void SomeMethod()
{
TestPartA();
TestPartB();
TestPartC();
TestPartD();
}
private void TestPartA()
{
// Do some testing...
try
{
if (somethingBadHappens)
{
throw new Exception("The error that happens");
}
}
catch (Exception)
{
// Cleanup here. If no cleanup is possible,
// do not catch the exception here, i.e.,
// try...catch would not be necessary in this method.
// Re-throw the original exception.
throw;
}
}
private void TestPartB()
{
// No need for try...catch because we can't do any cleanup for this method.
if (somethingBadHappens)
{
throw new Exception("The error that happens");
}
}
I have used the built-in System.Exception class in my example; you can create your own derived exception classes, or use the built-in ones derived from System.Exception.

You could perhaps try looking at the "Open/Closed" section of the SOLID Principle. In your example you could perhaps create an ITestRule interface which contains a method called CheckRule() that will updated your message and return a bool. You would then create an interface implementation for each rule you want to test, and add that class to a List<ITestRule> object. From the Redmondo example above, I would change to the following:
var discountRules =
new List<ITestRule>
{
new TestPartA(),
new TestPartB(),
new TestPartC(),
new TestPartD(),
};
You would then pass the new List<ITestRule> to an evaluator which will loop through each of the classes and runs the CheckRule() method.

I try to stick to a principle known as 'Fail Fast'; methods should fail when they are supposed to, and return immediately with details of the error. The calling method then responds appropriately (re-throw the exception to its caller, log the details, show an error if it's a UI-bound method, etc): -
http://en.wikipedia.org/wiki/Fail-fast
However, this does not mean using exceptions to control the flow of your application. Just raising an exception when you could deal with it is generally bad practice: -
http://msdn.microsoft.com/en-us/library/dd264997.aspx
In your case, I'd re-write your code as (for example): -
private bool SomeMethod()
{
bool success = false;
try
{
TestPartA();
TestPartB();
TestPartC();
TestPartD();
success = true;
}
catch (Exception ex)
{
LogError(ex.Message);
}
//... some further tests: display the error message somehow, then:
return success;
}
private void TestPartA()
{
// Do some testing...
if (somethingBadHappens)
{
throw new ApplicationException("The error that happens");
}
}

Related

Best practice for many try-catch blocks

I have many statements that can throw exceptions. Exceptions are not important.
My system accepts missing patient data fields.
patientData.PatientId = message.Find(...);
try
{
patientData.Gender = message.Find(...);
}
catch
{
// no gender, no problem
}
try
{
patientData.DateOfBirth = message.Find(...);
}
catch
{
// no DateOfBirth, no problem
}
// and many other try-catch blocks ...
What is the best way to write these statements that can throw exceptions but not critical?
In your example, you can create static TryFindMessage method in addition to Find. In case of exception just return false.
For example:
bool Message.TryFind(..., Message message, out string result).
But, if you wish some generic approach which you can use with anything, then you can take advantage of delegates and create some static helper.
You can use Action or Func in that case. Add another extension method which accepts Func if you need to return some value from executed function.
public static class SilentRunner
{
public static void Run(Action action, Action<Exception> onErrorHandler)
{
try
{
action();
}
catch (Exception e)
{
onErrorHandler(e);
}
}
public static T Run<T>(Func<T> func, Action<Exception> onErrorHandler)
{
try
{
return func();
}
catch (Exception e)
{
onErrorHandler(e);
}
return default(T);
}
}
And then use it so:
SilentRunner.Run(
() => DoSomething(someObject),
ex => DoSomethingElse(someObject, ex));
In case of Func, you can take result as well:
var result = SilentRunner.Run(
() => DoSomething(someObject),
ex => DoSomethingElse(someObject, ex));
I have many statements that can throw exceptions. Exceptions are not
important.
This can be dangerous, because exceptions can be thrown for different reasons, not only because of missing property.
I would advise instead of swallowing exception, modify code to return default value(null) when value is not found.
You can introduce new method in message class, for example FindOrDefault
// Pseudo code
public T FindOrDefault(string property)
{
return CanFind(property) ? Find(property) : default(T);
}
Usage of such method will be self explanatory
patientData.PatientId = message.Find(...); // Mandatory - must throw if not found
patientData.Gender = message.FindOrDefault(...);
patientData.DateOfBirth = message.FindOrDefault(...);

Watch for errors without returning error values? More info inside

I am having trouble Googling this, so here is an explanation:
I want to execute a list of methods from another class, one after the other, and have all my error handling take place like a try-catch scenario.
Something like this:
try
{
var thing1 = Worker.GetThing1(); //returns proper value, so continue
var thing2 = Worker.GetThing2(); //throws error with message
var thing3 = Worker.GetThing3(); //doesn't get done, stopped at 2
}
catch (ExceptionError errorMessage)
{
MessageBox.Show(errorMessage);
}
And the functions would look something like:
function GetThing1()
{
if (!success)
{
throw ExceptionError("this is an error message.");
}
}
The problem is I have no idea how to throw exceptions from another class, or if it is even possible to do.
Obviously, this is some serious pseudocode, so if I'm not being clear enough, let me know.
I made a quick console application to illustrate the point. The syntax for throwing a new error is throw new Exception(message); Code:
class Program
{
static void Main(string[] args)
{
try
{
var thing1 = Program.GetThing1(); //returns proper value, so continue
var thing2 = Program.GetThing2(); //throws error with message
var thing3 = Program.GetThing3(); //doesn't get done, stopped at 2
}
catch (Exception errorMessage)
{
Console.WriteLine(errorMessage.Message);
}
Console.ReadKey();
}
private static bool GetThing1()
{
bool success = true;
if (!success)
{
// This will NOT be displayed in the console.
throw new Exception("GetThing1 Error -> Not supposed to see this in output...");
}
return success;
}
private static bool GetThing2()
{
bool success = false;
if (!success)
{
// This WILL be displayed in the console.
throw new Exception("GetThing2 Error -> Expected, this has to be thrown!!!");
}
return success;
}
private static bool GetThing3()
{
bool success = true;
if (!success)
{
// This will NOT be displayed in the console.
throw new Exception("GetThing3 Error - > Not supposed to see this in output...");
}
return false;
}
}
To the guys saying 'all looks fine', please test your statements. Also, there is no standard class called ExceptionError in .NET, you can use the Exception class to catch all types of exceptions (but the poster said that he is using pseudocode, so we cannot hammer on the small details too much).
I think you have created custom exception class, and if your getthings function in diffrunt library than you should move this class to some common library and you should reference to both your libraries.
Thanks for the insight guys, I was so close with my original code. Here is what I ended up with:
class Program
{
static void Main(string[] args)
{
var worker = new Worker();
try
{
worker.GetThing1();
worker.GetThing2();
worker.GetThing3();
}
catch (Exception errorMessage)
{
Console.WriteLine(errorMessage.Message);
}
Console.ReadKey();
}
}
class Worker
{
public void GetThing1()
{
var success = true;
if (!success)
{
throw new Exception("This is an error message!");
}
}
public void GetThing2()
{
var success = false;
if (!success)
{
throw new Exception("This is an error message!");
}
}
public void GetThing3()
{
var success = true;
if (!success)
{
throw new Exception("This is an error message!");
}
}
}
It's so much easier to read and more efficient than trying to catch everything in if-else's. Thanks!

Good practice design pattern for Exception handling

I have exception handling code in every method for the below code for the bottom level methods
throw new Exception("The error that happens");
Is there any way I can avoid writing this code again and again in each method?
I am trying to write my own code and not using any log frameworks
private void TopLevelMethod()
{
try
{
SomeMethod();
}
catch (Exception ex)
{
// Log/report exception/display to user etc.
}
}
private void SomeMethod()
{
TestPartA();
TestPartB();
TestPartC();
TestPartD();
}
private void TestPartA()
{
// Do some testing...
try
{
if (somethingBadHappens)
{
throw new Exception("The error that happens");
}
}
catch (Exception)
{
// Cleanup here. If no cleanup is possible,
// do not catch the exception here, i.e.,
// try...catch would not be necessary in this method.
// Re-throw the original exception.
throw;
}
}
private void TestPartB()
{
// No need for try...catch because we can't do any cleanup for this method.
if (somethingshappens)
{
throw new Exception("The error that happens");
}
}
Only catch errors if you want to do something meaningful to them such as:
Wrapping the exception with a framework exception (e.g. SqlException. ADO.NET never passes you socket-level errors. It passes you a meaningful SQL error code)
Cleanup
Actually responding (e.g. retry, or insert default values)
Logging is almost never appropriate. The top level handler should log. Certainly not every method in the path should log. What a clutter for logs and for the code. Don't do that.
Simply don't swallow error information and let the error bubble out. That way there is no reason left to insert local logging code for errors everywhere.
If you prefer using Functional Programming like code style one way is to use callback error callbacks.
Example :
private void SomeMethod()
{
// do something
}
public bool Execute(Action act, Action<Exception> onErrorCallback)
{
var res = true;
try
{
act();
}
catch (Exception ex)
{
res = false;
onErrorCallback(ex);
}
return res;
}
And use Execute like this:
var successfull = true;
successfull &= Execute(SomeMethod, (ex) => { /* clean up */ });
successfull &= Execute(SomeMethod, (ex) => { /* clean up */ });
successfull &= Execute(SomeMethod, (ex) => { /* clean up */ });
successfull &= Execute(SomeMethod, (ex) => { /* clean up */ });
if (!successfull)
; // show user or something else
Graffito: Would you please give sample code example.Thankyou...
Your code refactored:
private void TopLevelMethod()
{
List<string> errors=new List<string>() ;
if (!SomeMethod(errors)) { /* Log/report errors/display to user etc. */ }
}
private bool SomeMethod(List<string> errors)
{
return TestPartA(errors) && TestPartB(errors) && TestPartC(errors) && TestPartD(errors);
}
private bool TestPartA(List<string> errors)
{
bool result = true ;
try
{
// Do some testing...
if (somethingBadHappens) { result=false; errors.Add("The error that happens"); }
}
catch (Exception ex) { errors.Add("Error in TestPartA: "+Ex.Exception.Message.ToString()) ; }
return result ;
}
private bool TestPartB(List<string> errors)
{
bool result = true ;
// Do some testing...
if (somethingBadHappens) { result = false ; errors.Add("The error that happens"); }
return result ;
}

Wrap an exception in a message without throwing it

I'm writing a service which's methods must not throw exceptions but should return a generic Message-object which contains the actual result of the method call and exceptions if any have occured. This Message class looks like this:
public class Message<T>
{
private List<Exception> exceptions = new List<Exception>();
public T Result { get; set; }
public void AddException(Exception x)
{
this.exceptions.Add(x);
}
public bool HasExceptions
{
get
{
return this.exceptions.Count > 0;
}
}
public IEnumerable<Exception> Exceptions
{
get
{
foreach (var exception in this.exceptions)
yield return exception;
}
}
}
Usually the implementation of a service method then looks like this:
public Message<int> MyServiceMethod()
{
var msg = new Message<int>();
try
{
// do something useful here
msg.Result = 42;
}
catch (Exception x)
{
msg.AddException(x);
}
return msg;
}
The caller can then handle exceptions if necessary.
var msg = service.MyServiceMethod();
if (msg.HasExceptions)
{
// Handle exceptions here
}
Now I have a service method with an argument which must be in a certain range. Since it feels natural for me to respond with an ArgumentOutOfRangeException if the argument is out of range, I implemented it like this:
public Message<int> MyOtherServiceMethod(int arg)
{
var msg = new Message<int>();
if (arg < 1)
{
msg.AddException(new ArgumentOutOfRangeException("arg", "Argument must be greater than 0"));
return msg;
}
// ...
return msg;
}
Basically this works. The only thing I'm missing is the stack trace of the exception. This is not a problem since I don't need that in my scenario. But it made me wonder, are there any other "side effects" which might cause trouble when the exception is used but not thrown?
You should use some construction that takes message and exception as arguments:
try
{
// do something useful here
}
catch (Exception x)
{
throw YourPreferredException(some_message, x);
}
This will make x available as yourPreferredException.InnerException property.
Also, I don't think it's a good design choice to have a method returning Message and running the try/catch block inside it (should be the other way around).
I would say that's not really the intended use of exceptions in C#. If you want a custom message then you just use the Exception constructor that takes a message and another instance of type Exception, this will give you a new exception with your custom message plus the original exception set as the instances InnerException property. You're just reinventing the wheel here with some custom 'message' class. If all you want to do is return a message (like you don't want to throw) then you should be taking the exceptions Message property and assigning it to some string or returning that string directly.
Here are a couple more idiomatic examples for handling your error;
Message ret = new Message();
try
{}
catch (Exception e)
{
ret.ErrorPropertyOfTypeString = e.Message;
}
return ret;
Message ret = new Message();
try
{}
catch (Exception e)
{
throw new Exception("My custom message here", e);
}
return ret;
Whatever you're doing, one of the two patterns above should probably used instead.

Adding Global Try Catch Exception

I implemented a Global Try Catch mechanism in this way. I added a seperate class called HandleException.cs
public static class HandleException
{
public static void GlobalTryCatch(Action action, object obj)
{
try
{
action.Invoke();
}
catch(SqlException ex)
{
obj.GetType().GetProperty("Success").SetValue(obj.GetType(), false);
obj.GetType().GetProperty("FailureMessage").SetValue(obj.GetType(), ex);
}
catch(Exception ex)
{
obj.GetType().GetProperty("Success").SetValue(obj.GetType(), false);
obj.GetType().GetProperty("FailureMessage").SetValue(obj.GetType(), ex);
}
}
}
And this way calling it.
public override Result<int> Update(UserProfile data)
{
var result = new Result<int> { Success = false };
HandleException.GlobalTryCatch(() =>
{
SqlParameter[] sParam =
{
DbHelper.CreateParameter("#UserId", ParameterDirection.Input, SqlDbType.Int, data.UserId),
DbHelper.CreateParameter("#FirstName", ParameterDirection.Input, SqlDbType.VarChar,100, data.FirstName),
DbHelper.CreateParameter("#LastName", ParameterDirection.Input, SqlDbType.VarChar,100, data.LastName),
DbHelper.CreateParameter("#Gender", ParameterDirection.Input, SqlDbType.Char,1, data.Gender),
DbHelper.CreateParameter("#Dob", ParameterDirection.Input, SqlDbType.Date, data.DateOfBirth),
DbHelper.CreateParameter("#ImageUrl", ParameterDirection.Input, SqlDbType.VarChar, 150, data.ImageUrl),
};
using(var sql = new DbHelper())
{
sql.ExecuteSpReturnScalar("UserProfile_Update", sParam);
}
result.Success = true;
}, result);
return result;
}
My questions are
Is this a standard practice for implementing global try catch mechanism or Is there any other standard way to implement this?
I had used this in GlobalTryCatch method. Whether this way we can assign value to a property by passing Generic Object?
obj.GetType().GetProperty("Success").SetValue(obj.GetType(), false);
Is this a standard practice for implementing global try catch mechanism
No, it is not. Moreover, mentioned "global try-catch mechanism" is a bad practice. Wrapping every method in try-catch assumes, that you definitely know, what to do after any exception has been thrown. In the real world this is false. Look at this sample:
void AnyMethod()
{
var result = // ...
HandleException.GlobalTryCatch(() => { /* action 1 */}, result);
// should we check result to continue?
// if so, this is a typical error-code approach, which annihilates
// all preferences, provided by .NET exceptions;
// if we shouldn't check it, what would be the behavior of our code,
// if the state is broken after action 1?
HandleException.GlobalTryCatch(() => { /* action 2 */}, result);
// the same questions
HandleException.GlobalTryCatch(() => { /* action 3 */}, result);
}
Similar approach from time-to-time being used to log exceptions (due to absence of out-of-box aspects inmplementation in .NET):
void Execute(Action action)
{
try
{
action();
}
catch (Exception e)
{
Logger.Log(e);
throw;
}
}
T Execute<T>(Func<T> func)
{
try
{
return func();
}
catch (Exception e)
{
Logger.Log(e);
throw;
}
}
but:
1) it logs full exception information (e.g., your code is missing stack trace and inner exceptions);
2) it re-throws the same exception (this allows to use all benefits from .NET exceptions);
3) it wraps only limited number of top-level methods, not every method.
Whether this way we can assign value to a property by passing Generic Object?
You could do something like this:
interface IActionResult
{
bool Success { get; set; }
string FailureMessage { get; set; }
}
public static void GlobalTryCatch<T>(Action action, T obj)
where T : IActionResult
{
// ...
}
but this doesn't cancel answer on your 1st question.
You can use http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx (or http://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx for WPF applications).
Generally it is not a bad idea to do something meaningful during this events - logging the exceptions (or sending them to admin) and displaying a message to user (something like "Sorry, error occurred, contact your admin please").
But as others said - you should handle the excpetions in your methods where you can do something meaningful with them, not on global level. And even if it is not mandatory in c#, it's a good idea to add to comments that your method can throw some kind of exception on certain circumstances.

Categories

Resources