为什么“log and throw”被认为是反模式?

时间:2011-07-10 08:03:37

标签: logging exception-handling anti-patterns

围绕this article的讨论引发了这个问题,我没有得到任何好的答案。

为什么要记录你的异常,然后重新抛出它(当然保留原始的堆栈跟踪)是个坏主意,如果你不能处理它呢?

4 个答案:

答案 0 :(得分:88)

我认为答案主要是因为如果你无法处理它,你为什么要抓住它?为什么不让任何人能够处理它(或者除了处理它之外别无选择)记录它,如果他们觉得它是值得记录的?

如果你抓住并记录并重新抛出它,那么上游代码就无法知道你已经记录了异常,因此同样的异常可能会被记录两次。或者更糟糕的是,如果所有上游代码都遵循相同的模式,则异常可能被记录任意次数,一次针对决定捕获它的代码中的每个级别,记录它,然后再次抛出它。

也有人可能会争辩说,因为抛出和捕获异常是相对昂贵的操作,所有这些捕获和重新抛出都无助于运行时性能。它也不会在简洁性或可维护性方面帮助您的代码。

答案 1 :(得分:38)

如果实体捕获并重新抛出异常有理由相信它包含的信息不会在调用堆栈中进一步记录,那么Log-and-throw是一个很好的模式 - 至少不是以最理想的方式。可能出现以下几个原因:

  1. 可以在应用程序层边界捕获并重新抛出异常,并且可能包含特权信息。数据库层允许例外说明,例如,这是不好的。 “尝试将重复键'fnord'添加到字段'users'”以到达外部应用程序层(这可能反过来将其暴露给用户),但是对于数据库的内部部分来说,抛出这样的异常可能很有用用于捕获它的应用程序接口,安全地记录它,并重新抛出一个稍微不那么描述性的异常。
  2. 异常可能是外层可能希望在没有记录的情况下处理的异常,但内层可能知道外层没有的东西,这表明记录可能有用。作为一个粗略的例子,中间应用程序层可能被编程为尝试连接到一个服务器,如果这不起作用,请尝试另一个。当服务器停机进行维护时,使用“连接失败”消息充斥应用程序的日志可能没有用,特别是因为 - 从应用程序的角度来看,一切正常。将与连接失败有关的信息转发到与服务器关联的日志记录资源可能很有用,然后可以过滤日志以生成服务器上升和下降的报告,而不是每个连接尝试的日志。 。

答案 2 :(得分:14)

我想最简单的原因是你通常只有一个顶级处理程序为你做这个,所以没有必要用这个异常处理来污染代码。

横切关注的论点基本上是浪费时间处理与您无关的错误。最好让错误冒出调用堆栈,直到找到合适的处理程序。

在我看来,你应该抓住异常的唯一时间是你可以对结果做一些有用的事情。仅仅记录日志是没有用的,因为你可以进一步集中这项工作。

答案 3 :(得分:7)

IMO登录和投掷明显违反了最低惊喜原则。

如果在调用堆栈的上游正确处理异常,则可能根本不值得输入错误日志。然后找到错误日志条目会让人感到困惑。