C# - 尝试/捕获日志和Rethrow是一种不好的做法?

时间:2017-10-29 10:38:35

标签: c# logging exception-handling

我可以看到几个帖子,其中强调在中心位置或过程边界处理异常的重要性被强调为一种良好的做法,而不是乱丢每个代码块在try / catch周围。我坚信我们大多数人都理解它的重要性但是我看到人们仍然以 catch-log-rethrow 反模式结束,主要是因为在任何异常期间缓解故障排除,他们想要记录更多的上下文具体信息(例如:方法参数传递)和方法是围绕try / catch / log / rethrow包装方法。

是否有正确的方法来实现这一目标,同时仍然保持异常处理的良好做法?我听说过像PostSharp这样的AOP框架,但想知道这些AOP框架是否存在任何不利因素或主要性能成本。

谢谢!

1 个答案:

答案 0 :(得分:1)

在这里和那里进行一些搜索之后,我会考虑自己回答:

尝试/捕获/抛出/日志遍布方法和代码不是一个好习惯。当你想到这个时,你应该问下面的问题:

您将如何具体处理该异常?如果回答是吞下,我会说你需要三思而后行。如果状态由于在catch块中吞噬异常而被破坏,那么调用堆栈中的某些方法可能会再次抛出异常 - 现在该如何处理此异常?同样的周期?它很快就会引发你更大的混乱。

当您确实知道可以对它执行某些操作时,您可能会谨慎地遵循捕获异常的模式(例如,在sql超时异常的情况下吞下并重试)此外,您可能希望立即捕获异常,以备您需要时使用在日志中捕获更多上下文特定的细节。在这种情况下,catch并重新抛出包含原始异常的新异常作为内部异常。

简而言之 - 在应用程序根级别或服务边界级别进行异常处理/日志记录是件好事。

话虽如此 - 在集中位置,您还可以配置如何处理特定类型的异常。例如:

作为业务层数据验证的一部分而抛出的错误请求异常只会返回400个错误请求(如果是Web应用程序)

如果异常是SqlException类型 - 将一般异常抛出到具有一些跟踪ID的客户端,并将详细的异常记录到eventlog / db / application insight等。

如果业务层中的外部系统有任何异常 - 再次向客户端发送通用异常并向提供外部服务的系统发送通知电子邮件。

这些只是一些例子,围绕异常处理的良好实践也隐含地促进了良好的设计。例如:为什么不安全保护以确保传递给方法的参数不为null并抛出ArgumentNullException而不是捕获NullReferenceException然后通过在方法级别使用try / catch / log来捕获参数值。

我在此处发布了有关异常处理和记录良好做法的问题。请检查它是否有很好的辩论和讨论与各种建议和良好做法。