捕获所有异常并将其作为特定类型的异常重新分类是一种好的做法吗?

时间:2010-10-22 08:38:07

标签: design-patterns language-agnostic exception-handling

捕获所有异常并将它们作为特定类型重新抛出是一种好习惯 - 基本上是对从应用程序的特定部分(或服务)抛出的所有异常进行分类吗?

类似的东西:

//  This class is used to label all the exceptions occured on 
// Race Cars Service calls as RaceCarsServiceException
public class RaceCarsServiceException : Exception
{

 public class RaceCarsServiceException (Exception e) 
               : base("Something went wrong!", e)
  {
     // Basically I assign the exception e as the inner exception 
     //by using the constructor method of Exception class
  }

}

public class RaceCarsService
{

// Some member fields, methods etc. here

 public double GetMaxSpeed(CarModel model)
 {
   try 
     {
       return (double)_carsWebService.GetMaxSpeed(model.ToString());
     }

   catch(Exception e)
     {
       throw new RaceCarsServiceException(e); // So all exceptions are rethrown 
                                           //as type of RaceCarsServiceException
     }
 }
}

3 个答案:

答案 0 :(得分:2)

这是一个巨大的争论起点问题之一。

如果您要抛出自定义异常,则不应该像示例中那样直接映射内部expcetion。您应该进行某种条件检查,以区分您对特定自定义异常的特定需求与可能抛出的各种可能异常。

在我看来,如果在正确的地方适度进行,这样做会非常有益。

在我构建的一个应用程序中,我们需要能够使用传入的参数来回溯每个函数调用,以便我们可以识别导致异常的精确事件链。

有时内部异常不够细化。或者您需要抛出一个异常,告诉您哪种进程失败。

例如,如果您的代码需要是事务性的,但是需要处理多个服务,因此需要一些manaul代码来处理事情,那么事务异常是适当的,就像事务回滚异常一样(这通常意味着你在一个痛苦的世界。)

我认识的人强烈认为自定义异常是一件坏事。原因在于它很容易被带走,并且创造了太多的自定义删除,这对其他人来说毫无意义和无用。

我发现的一件事是,RecordDoesNotExist异常感觉就像DAL异常,但实际上它发生并且最常在业务逻辑中处理。

总而言之,我认为他们在适当的地方,适度和充分的理由是一个好主意。但很容易与他们相处。

您应始终将原始expcetion传递到自定义异常并将其存储在那里。这样做可以保留堆栈跟踪,并在异常中存储堆栈跟踪,以便抛出自定义的跟踪点。

我需要在审核时使用自定义删除。

编辑: 在跟随另一个答案中的链接后,我得说这是一篇关于删除的好文章

Exception Handling Best Practices in .NET

与此相关的反模式

Exception Anti-Patterns

答案 1 :(得分:1)

此代码示例不会重新抛出异常,但会在其他代码上创建新的异常。

该代码将创建新的堆栈跟踪。

good practice for exceptions

答案 2 :(得分:0)

没有必要这样做(至少在你的例子中)。当试图调用可能抛出异常的方法时,分别处理不同类型的异常。

try
{
    AMethodMayThrowExceptions();
}
catch (FileNotFoundException fileEx)
{
      //maybe create the file and retry
}
catch (TimeoutException timeoutEx)
{
      //maybe a retry after n seconds
}
catch (Exception ex)
{ 
      //other exceptions which I don't care
      //just a prompt of ex.Message or something
}

如果您使用单个RaceCarsServiceException会有什么用?

catch (RaceCarsServiceException ex)
{
    // now it's supposed to have a `ErrorCode` property, or an inner exception
    if (ex.ErrorCode == ErrorCode.File)
        //file exception, everything is the same with FileNotFoundException
    else ...
}

你只有麻烦,代码不太可读!