异常捕获:何时不应该捕获异常?

4

我一直在PHP的Zend框架内编写许多小型库(一堆类)用于我的应用程序。我也一直在库方法中捕获这些异常并将它们记录到文件中。

然后突然间,我遇到了一个问题:即使在我预期由于致命错误而退出的情况下,使用这些库的主要应用程序仍不会退出。这个问题的原因是下面的代码继续执行到最后 - 它本不应该这样。

似乎在库类中捕获并记录大部分错误(除非特殊情况)并不是一种好的做法。它们应该始终抛出错误?这是否正确的假设?

如果有人能为我解答这个问题,我将不胜感激。


当我说“按原样抛出错误”时,我并不是说完全不捕获它。只是我会让调用者/控制器来捕获错误,而不是在库类中捕获它。 - Subrat Basnet
3个回答

6
在任何语言中,异常的一般哲学是它们传达了“异常情况”。您应该相应地使用它们。如果您最终用try块包围每个函数调用,则出现了问题。异常的设计恰好是为了使错误处理变得逻辑化,而不需要程序员跟踪所有可能的错误路径。因此,您应该在那些可以对其做出有意义的响应的点上精确捕获异常。如果您想到的唯一更好的方法是中止并传播错误,则没有捕获异常的意义。另一方面,如果有一些错误可以合理地进行反应,请捕获这些错误,并重新抛出其他任何内容。一个典型的例子是如果您正在处理大量文件。如果解析逻辑中的任何地方出现错误,则您无法做任何事情,即使解析可能会下降许多函数调用。但是,在主循环中,您可以尝试解析每个文件,如果出现异常,则捕获它,跳过该文件并继续下一个文件。如果您正在编写库函数,则可能希望在整个函数周围拥有一个最终的try块;这在某种程度上取决于您。只需干净地记录用户必须从您的库中期望哪些异常。

本来也想回答同样的问题,但这个回答已经很好地涵盖了。总之,在你能够实际处理异常的情况下,一定要处理它们。 - Christian
是的 - 绝对不要试图在各个地方捕获异常。如果您像使用C函数返回值一样使用异常,那么肯定有问题... - Kerrek SB

4

捕获和处理所有异常是一个好主意。如果您不确定是否可以安全地忽略异常(例如,由您自己的代码引发的异常),请显示错误页面。不要简单地重新抛出它,因为向用户呈现空白页面、Web服务器的默认错误页面甚至PHP错误消息都是最糟糕的情况。


好的,这意味着我应该设计我的库、模型类,让调用者知道它是否应该捕获异常?比如说,我的库不会通过设计来捕获任何异常 - 我只是让调用者/控制器来处理,这样是否是一个理想的设计? - Subrat Basnet
如果您在代码中使用PhpDoc(DocBlocks),则可以使用@throws标记。一些语言(如Java)会自动执行此操作,因为您必须在方法/类前缀中使用“throws”子句,就像您使用“extends”子句扩展类一样。 - Christian

0

这取决于网站是否处于生产状态或已发布产品。最后你想做的事情就是向用户显示堆栈跟踪信息。如果你预期会出现可能导致严重问题的错误,那么就要捕获并处理它。


同意,但我关心代码设计。如果我的库没有捕获任何异常-我只是让控制器来处理异常,这样做好吗? - Subrat Basnet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接