null?对象?异常?到底应该如何返回错误信息

Posted 救赎之道就在其中

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了null?对象?异常?到底应该如何返回错误信息相关的知识,希望对你有一定的参考价值。

这篇文章记录我的一些思考。在工作了一段时间之后。

问题的核心很简单:到底如何返回错误信息。

学生时代,见到过当时的老师的代码:

1 if (foo() == null) {
2 
3 }

 

当然,这位老师是一位比较擅长c/c++的老程序员,所以他的代码其实使用c写的。但是意思和这段代码类似。当时,我很好奇为什么要对一个方法的返回值是不是null进行判断。现在当然很清楚了:在很多win32的API里面,是通过返回值为null来传递“函数调用失败”这一种信息的。

那么,这么做好吗?

我翻看了很多的博客,大致上说这种写法不好的占多数。最重要的理由如下:

  • 无法展示更详细的错误信息
  • 容易让调用者忽略

这种说法基本还是有道理的。因为返回值为null,确实很明显得存在这两种问题。

对于第一点,其比较关键的影响就是,既然不知道更多信息,也就无法在日志中体现。从而不能针对可能出现的多种异常进行不同的日志打印和处理。曾经也发生过因为缺失了日志打印,导致花很多时间来定位一个问题的情况。尤其是线上环境不比本地随意debug,一个简单的问题经过几次这种“信息丢失”之后,就有可能成为一个“疑案”。

而第二点,更是严重影响系统安全性、稳定性。人都有不小心的时候,如果忘了对某个接口的返回值进行校验,就会导致代码逻辑是按照“这件事已经发生并且正确发生”写的,但是实际执行过程中发生了错误。一方面比较难排查,第二方面是可能导致一个问题在另外的地方爆发出来。

 

那么是不是绝对不能这么做呢?其实也不尽然。简单来说,如果调用方在系统内部、代码执行逻辑可控、在返回null之前有正确的日志打印、调用方对这个异常确实没有办法处理。满足这几个条件就可以使用返回null。但是还是具有危险性。

 

这个问题的改进方案是返回一个对象。比如写一个Result对象。

 1 public class Result {
 2 
 3     private Integer code;
 4 
 5     private String message;
 6 
 7     private Object data;
 8     
 9     // getter and setter
10 
11 }

 

这样就有一个优化:能够返回错误的信息和一些数据。本次方法成功了吗?如果失败需要打印什么信息?如果成功,是不是需要一些内容?

 

但是这种写法也有问题。

最主要的是其适用性问题。就是说如果很多方法使用同一个Result,能保证都能通过这种方式返回其需要的数据吗?一些特别的方法返回的东西不能够使用一个Object进行转化。(或者说这样做代价不小)

其次,很多代码业务逻辑极其简单,如果强行使用结果类进行封装,反倒有画蛇添足之嫌。

最后,如果要严格使用这个类,代码开发的代价很大。

那么这种做法适合什么场景呢?一句话:对外接口。一方面我们要按照一个统一的规则去返回信息(正确或者错误)。第二方面,很难要求调用方去捕获我们的异常。如果他们忘了捕获,是不是就有可能会造成更严重的情况?所以,这种情况下,我们需要告知调用方失败信息。但是又不能要求对方做出多少改变。

 

 

最后一种解决方案是抛异常。

 Effective Java里面用一句话解释什么时候需要抛异常,什么时候不需要。“当你对异常什么也做不了的时候,就不要抛异常”(大意,有可能记错了)。

 

、、、、、、、、未完待续

 

以上是关于null?对象?异常?到底应该如何返回错误信息的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的云函数返回带有代码 INTERNAL 的异常,并且详细信息为 null 并带有未处理的错误 TypeError: is not a function

如何决定一个函数是返回错误还是产生异常? [复制]

JQuery $.ajax 捕获异常信息

如何显示方法是不是可能返回 null

Java:初始化错误的适当异常

异常被捕后返回null设计错误[关闭]