国外大佬给出的三种处理异常的套路!

漫画编程

共 3883字,需浏览 8分钟

 ·

2020-01-17 23:22

作者:Radek Hecl

原文链接:

https://dzone.com/articles/good-exception-handling


Oh no, don't do this to me...

译文:

哦,请不要这样写……

// 写一句注释跳过异常
try {
throw new IOException("Made up");
} catch (IOException e) {
// 跳过
}
// 记到日志里,继续处理
try {
throw new IOException("Made up");
} catch (IOException e) {
log.error("blah blah blah", e);
}
// 标记 TODO,不做任何处理
try {
throw new IOException("Made up");
} catch (IOException e) {
// TODO - 处理异常 (;
}

.... and still, I am finding those catch blocks inside various projects. This is a great way to suppress the problem — for a short period of time. A few weeks or months later, this will become a nightmare for developers. Walking through the old log files and trying to figure out what went wrong is definitely not that most people want to do. Therefore, let's avoid that.

The first rule is that catch blocks are here to handle exceptional situations. Logging exceptions and moving on is not considered as handling. The only case when it makes sense to suppress exception is during the closing of the resource after a prior exception (this case isn't covered within this article; if you are interested, then here is an old yet still very good blog post written by McDowell).

There are three basic patterns of how to handle exceptions: translate, retry, and recover.

Translate is often used when you have to deal with a checked exception, your method can't bubble it up, and recovery is not possible. In such cases, it is appropriate to translate it into a runtime exception and throw up. Then, the runtime exception is typically handled in the framework level. Retry is useful when dealing with unreliable services. It makes sense only if retrying makes sense fundamentally. The good example is retrying to overcome network interruptions. Recover is good when the strategy for doing that is defined. For example, you can write data to the local storage if sending over network fails. Of course, then it's necessary to define what to do with that file.

In addition, the mentioned patterns might be combined. Examples are as follows.

译文

我在各种项目中发现了这种 catch 语句。这是一种“好办法”,可以在短期内掩盖问题。然而几周或几个月后,这些代码将成为开发人员的噩梦。绝大多数人可不想读日志查问题。因此,还是让我们避免这种情况。

规则一:catch 语句是用来处理异常的,把异常记到日志里然后继续执行不算处理。唯一的例外是,在发生异常后关闭资源(本文不讨论这种情况;如果感兴趣,可以参考这篇 McDowell 的博客,虽然写的时间比较早,但内容很不错)。

有三种处理异常的基本模式:转换(translate)、重试(retry)和恢复(recover)。

转换经常用于处理受检异常(checked exception),在方法中异常无法抛出,并且无法恢复时使用。在这种情况下,将其转换为运行时异常(runtime exception)而后抛出是最合适的做法。接下来,运行时异常通常由框架处理。在处理不可靠的服务时,重试非常有用,前提是重新尝试有意义。一个很好的例子就是网络中断重试。如果定义了这种策略,那么就能够恢复到正常状态。例如,如果通过网络发送数据失败,可以将数据写入本地存储。当然,这时就必须定义如何处理该文件。

此外,上面提到的模式可以组合,比如像下面这个例子如下。

// 转换
try {
throw new IOException("Made up");
} catch (IOException e) {
throw new RuntimeException(e);
}
// 重试5次后放弃
boolean end = false;
int count = 0;
while (end == false) {
try {
// 发送信息
if (true) {
throw new MessagingException("Made up");
}
end = true;
} catch (MessagingException e) {
if (count >= 5) {
// 尝试5次放弃。
throw new RuntimeException("was not able to send message even after five tries", e);
}
++count;
try {
Thread.sleep(30000);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
throw new RuntimeException(e1);
}
}
}
// 恢复:如果传输失败记录到文件
try {
// 发送信息
throw new MessagingException("Made up");
} catch (MessagingException e) {
try {
// 写文件
throw new IOException("Made up");
} catch (IOException e1) {
// 如果写文件失败,不再进行恢复
throw new RuntimeException(e1);
}
}

If everything fails, then this way will at least guarantee that you will be aware of the problem. In addition, it will provide you always the true cause of the issue; therefore, you will be able to quickly identify where the problem is!

Happy handling!

译文

如果一切都失败了,那么上面这种方法至少可以确保你能意识到问题所在。此外,它还提供了问题的真正原因,从而让你能快速定位问题。

祝编程快乐!



推荐阅读:


031af0d171c55f1ac4bc59f4fe6b8e90.webp喜欢我可以给我设为星标哦031af0d171c55f1ac4bc59f4fe6b8e90.webp

3a05d22d062571131a8f796d105313ee.webp

好文章,我 在看 

9870b562c0af92270fa4450925286c87.webp
浏览 13
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报