简体   繁体   中英

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:

  1. Wrapping the exception with a framework exception (eg SqlException . ADO.NET never passes you socket-level errors. It passes you a meaningful SQL error code)
  2. Cleanup
  3. Actually responding (eg 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 ;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM