分布式环境中是否允许枚举作为返回值

《阿里巴巴JAVA开发手册》禁止枚举作为返回值的规定的看法

Posted by caotc on March 10, 2018

使用枚举作为返回值可能造成的问题其实大家都知道就是客户端和服务端版本不一致的话,会造成反序列化异常.

于是《阿里巴巴JAVA开发手册》对于这个问题的处理办法就采取了尽量避免异常出现,所以禁止定义枚举为返回值.

首先,枚举不作为返回值,那么作为替代品只能是返回code.

那么本地系统收到了一个未定义的code,该怎么处理呢?

想来想去,无非有两种情况:

1.本地系统根本没用到这个属性,完全无所谓

2.if或者switch中进入default流程.

(1)default流程中直接忽略不进行任何操作

(2)default流程中当做某个默认值来对待

(3)default流程中直接抛错(那还不如Fail Fast,就早点序列化异常更好)

但是,实际上这个操作对于枚举类型一样能做.

如果只是想要这个效果的话,完全可以对于反序列化方法进行修改,对于枚举类型的反序列化转换改为不抛出异常,同样忽略或者赋值为默认值即可.

这个规定简直就像是先把反序列化时无效枚举值必须抛出异常作为固有思维先作为前提规定,然后发现在这个前提下,只能catch反序列化异常,不符合编程原则,于是倒回来修改返回值规定.

实际上我认为这是错误的想法.

Effctive Java中之所以推荐用枚举代替所有常量Code,原因如下:

1.类型检查,有效性检查

2.枚举作为一个类,可以有自己的属性(通常应该是常量,我没遇到过不是的情况)以及自己的方法(否则只能用switch来写,实际违反原则)

3.和常量相比,无需查看文档和源码就能直接知道所有可能返回值,方便编码.

然而这里的问题就出在第一点上,实际上分布式环境下1并不是必然的.

如果业务处理中允许某个接口返回值有未定义内容,那么在反序列化中就不该对此抛出异常,不必死守1.

同时,从第2点和第3点来看,这样限制枚举的使用范围造成的影响是极大的.

将有自己属性,自己方法实现的枚举改写为code和其他方法的配合,需要的代码量上升不少,而且代码腐烂度极大增加.

枚举的方法从本身转换出来后,有两种写法:

1.使用到的地方switch或者if else来进行分支处理,于是又衍生出

(1)如何保证常量类型

(2)如何保证该类常量值增加时,所有方法都进行相应修改?

等等,根本是开倒车.

2.自己完成多个实现类并使用单例模式map全局管理,本质等同于自己在代码层面实现一套java的枚举机制.

这根本多此一举,完全就是绕了一大圈才达到了简单的对于反序列化方法进行修改的效果.

所以我认为这个规定不太正确,十分值得商榷.