使用try catch的n层

时间:2013-10-29 03:10:28

标签: exception-handling

我正在开发一个n层应用程序,只在我的表示层执行try / catch。如果数据层或业务层中发生错误,则表示层中的try / catch会捕获此错误。这是好的,还是应该在每一层的每个方法中使用try catch?

2 个答案:

答案 0 :(得分:1)

一般情况下,最好将异常捕获到接近发生的位置,以允许代码可能做一些事情来修复/适应/响应问题。这种“做某事”取决于具体情况。例如,如果您的服务层调用失败,您可能需要重试该调用,因为该服务可能太忙;而如果您的存储过程被破坏,那么重试的次数无关紧要,它将被破坏,直到数据库中的逻辑得到纠正。

如果您只想记录错误,那么将错误发送到接近发生位置的错误就不那么有用了。

我曾经参与过的每个项目在应用程序的每一层都有try-catch块。

try-catch的一个推论是Fail Fast的概念,它通常表示当系统立即失败而不是缓慢失败时,调试效率会提高(阅读:小时,几天,几周,几个月甚至几小时后)多年的经营)。

在.NET Framework中快速失败的一个好例子是Convert.ToInt32()与使用(int)的直接投射的使用,如下所示:

int? settingValue = Convert.ToInt32(SomeSettingString);

if(settingValue == null)
{
    // Do something here
}
else
{
    // Do something else here
}

如果SomeSettingString可以转换为int,则将值设置为并执行Do something else逻辑。假设从现在开始一年,设置发生更改并返回null,因为转换失败,现在突然执行Do something here逻辑,这是一个调试冒险,可以发现这种情况发生,如果你能发现的话。像这样的大多数问题似乎只发生在PRODUCTION而不是DEV。

现在让我们看看同样的事情,但是快速失败,就像这样:

try
{
    int settingValue = (int)SomeSettingString;
}
catch(Exception ex)
{
    // Fail fast and throw exception
    throw new Exception("Fail fast");
}

现在,当设置字符串导致转换为int失败时,会立即发生异常。

注意:请注意快速失败可能会被“吃掉”异常的空catch块破坏。应该避免使用空try块的catch块,因为它们总是会导致“吃掉”异常情况。

不要这样做:

try
{
    // Exception waiting to happen here
}
catch(Exception ex)
{
    // Catch-all, because all exceptions derive from Exception class
    // So this will eat exceptions and pretend like they never happened
}

答案 1 :(得分:0)

这是你想要在任何级别避免的:一堆看起来像这样的方法:

void method()
{
   try 
   {
      // some code here that may potentially throw an exception
   }
   catch ( /* anything here */)
   {
      // code right here to handle that exception
   }
}

如果你正在做的事情,你也可以回到VB旧的On Error Goto系统,因为你没有获得任何东西。异常为错误处理提供了两个主要优点:能够以不同方式轻松处理不同类型的错误,以及在程序的调用堆栈中进一步捕获错误的能力。这是你在这里问的第二个优势。

所以我们看到你确实希望允许异常“冒泡”到更高层,因为它是我们为什么有异常的一个重要部分......但是你总是想在表示层处理它们吗?不,我们可以做得更好。有时,可能存在关于如何从数据层响应某些异常的业务规则。有时,数据层本身可能能够处理异常并从异常中恢复,而不会警告其上方的层。

另一方面,异常的一个优点是它可以让你在较低层中编写更简单的代码,从错误处理代码的正常程序执行流中获得更少的中断。这样做的代价是在表示层中放置更多的try / catch。同样,这并不意味着表示层是唯一可以处理它们的地方,但这是一个努力确保它们不会超出您的表示层未被捕获的地方。如果您无法在其他任何地方处理它们,请确保在表示层中捕获它们并以友好的方式向用户显示它们。使用相同的机制来记录或报告异常也是一个好主意,这样您就可以获得有关应用程序失败位置的良好指标,然后使用该信息来提高应用程序的性能。

当您确实遇到了最后一个异常处理程序时,您可能还需要考虑终止该应用程序。如果你真的有意想不到的事情发生,那么未处理的异常使它通过表示层,有一个有效的思想学派,表明继续运行程序可能不是一个好主意。但即使在这种情况下,您也希望捕获并尝试报告异常,然后尽可能优雅地崩溃。