以下是编码良好实践的方法吗?
try {
//my code here
} catch (Exception e) {
logger.error("Some error ", e);
throw new MyCustomException("Some error ", e);
}
而且,我应该......
我理解使用throw
我可以在callstack的另一部分中捕获异常,但是可能额外的日志记录有一些隐藏的好处并且也很有用。
我在某些情况下使用两者,记录并抛出异常。特别是,它在API中很有用。通过抛出异常,我们允许调用者处理它,通过记录,我们可以自己确定它的根本原因。
并且,如果调用者在同一系统中,那么如果我们在每个catch中添加日志,则会有重复的日志。
通常情况下,我认为你应该记录或重新抛出。同时执行这两个操作只会导致每个图层一次又一次地记录异常,这使得日志难以阅读。更糟糕的是,很难弄清楚你实际拥有多少错误 - 是7个错误,还是记录了相同错误的7层应用程序?
这意味着如果您抑制异常,则记录它并说明为什么您认为不值得重新抛出。
另一方面,如果你重新抛出异常,你知道它会被捕获和被抑制(在这种情况下捕获器会记录异常及其被抑制的原因),或者它会从你的应用程序中冒出来并成为由app容器捕获,它将捕获并记录异常。每个异常在日志中只显示一次且仅显示一次。
使用您建议的模式时,通常会在日志中多次报告错误事件。此外,在阅读日志时,它们之间的连接并不总是很简单。
就个人而言,我更喜欢只记录错误事件一次,并在较高的调用级别中执行。因此我几乎从不记录并重新投掷。我通常让异常进入调用堆栈,直到它到达可以某种方式处理的上下文,这就是我记录的地方。
如果异常被包装并正确地重新抛出,则应该从单个日志消息的堆栈跟踪中清楚地看到上下文。
我认为您可能需要明智地使用该模式。正如您上面所写的那样,对于每个异常,您将记录2个堆栈跟踪,这可能会填充您的日志中过多的信息。
关于伐木与投掷,它们是两个独立的问题。抛出异常会中断执行,阻止任何进一步的工作,也许回滚数据库提交等。日志记录只会将信息转储到日志文件(或其他地方)。它更适用于调试,而且通常更难以测试。
正确的答案是:“这取决于”
您通常希望记录您捕获的异常,因为它们对应于出错的地方。这就是为什么代码分析工具(如声纳)会在您不记录它们时发出警告的原因。
考虑以下taks:解析文件。在解析文件时,您实际上尝试解析每一行。有时某些行会出错,因此您不希望因此而停止解析文件。在这种情况下,您可能只想记录错误的行并继续保存文件。但是,假设在某些时候您在阅读时遇到I / O异常(例如,某些其他程序在您访问它时删除了该文件)。
在这种情况下,您可能希望在日志中记录遇到的错误,并抛出一个新的异常以停止处理整个文件。
简而言之,你必须考虑做什么是最好的事情。但这两种做法都不错。