【发布时间】:2012-10-24 04:19:10
【问题描述】:
我见过几种异常处理方法。我见过的两种最常见的模式是:
- 尝试捕获每个函数,记录异常并重新抛出
- 在最顶层尝试 catch(如 main 函数),记录异常并重新抛出
如果有的话,哪种做法更好?或者在什么情况下您会选择一种方法而不是另一种方法?
【问题讨论】:
我见过几种异常处理方法。我见过的两种最常见的模式是:
如果有的话,哪种做法更好?或者在什么情况下您会选择一种方法而不是另一种方法?
【问题讨论】:
这取决于您的应用程序并且是一种设计选择,尽管选项 1 非常混乱。您应该只捕获您准备以某种方式处理的异常,而不是任意捕获每一个。在大多数语言中,异常都会有一个堆栈跟踪供您查看,因此不需要在每个级别进行日志记录。当我说以某种方式处理时,可能是记录并重新抛出,或者可能是记录,通知用户一些错误,然后继续运行
附带说明,您不应该在代码中使用异常作为逻辑。如果您发现自己使用 try catch 块作为流控制,那么您应该考虑重新设计。例外就是这样,例外。
【讨论】:
选项 1 被认为是不好的做法,应该避免,而选项 2 是您应该遵循的最佳做法。
异常处理的原则是默认让异常自然抛出并在顶层捕获它们,就像选项 2 一样。只有一种情况你应该捕获异常是你想基于异常做一些业务逻辑。不处理业务逻辑,不要抓。
选项 1 的更多缺点:
大量的 try-catch 和 re-throw 会降低您的代码的可读性,
考虑在每个方法中捕获异常并记录它们将使日志文件记录相同的异常信息,这是不必要的。
【讨论】:
我看到最多的做法是:
捕捉那些你准备好处理的异常。例如,插入重复的主键,捕获它,并向用户显示适当的消息,以便为记录输入唯一的内容。
对于应用程序的其余部分,库中不会有异常处理。这样如果发生异常,它可能会弹出到上层,在那里可以进行适当的处理。
你可能会看到这篇文章:Exception Handling Best Practices in .NET
【讨论】:
我通常会完全避免选项 1,因为我看不到真正记录异常通过的每个函数的价值。你通常主要关心异常发生的地方。可能需要知道它是如何到达那里的确切流程,但您可以从异常调用堆栈中获得。
我用于处理异常的原则是仅在我对其进行处理时才捕获它们。如果 catch 的唯一目的是重新投掷,那么接住它就没有意义了。 但是,如果我确实抓住了它,然后记录它/用自定义的特定异常包装它/处理它,这就是一个足够好的理由。我通常发现此类任务并非在每个函数中都完成,但最常见的是在层/层边界
【讨论】: