Java Enum小心使用,它可能增加系统耦合性
关于在SOA环境中使用Java Enum的一些经验已经在《服务化的行军中:Enum使用,快乐的痛苦》一文中进行了讲述。
随着项目的深入,在某些环节使用Enum的不爽之处,上升为一些设计方面的选择问题。
- Enum不适合作为通用类的属性来使用
- Enum不适合作为服务接口的参数来用
在我们的代码中,我看到如下一个情况,有关类:UserPrincipal,它被整个分布式系统中的所有系统共同使用,从包的放置位置:net.esbzone.comm.security就可以看出它的通用性。突然某天,看到有同学在这个类加入了一个Enum属性,这个Enum属性还是另外一个业务系统B内部定义的一个通用常量【这个常量的确很是通用,表示用户类型】。这个例子,首先导致UserPrincipal与业务系统B产生了紧耦合,间接导致所有系统与业务系统B产生了耦合;其次即使它定义在net.esbzone.comm.security包中,也间接导致UserPrincipal与具体业务产生了关联,会增强外部系统对Enum的耦合度,从而削弱了UserPrincipal的独立性;此外一旦Enum发生变化,所有依赖与它的业务系统都要发生变化,代码依赖级别的变化。
往往,Enum的业务语义太强,与场景的关联性太密切,一旦环境发生了变化,Enum的值就可能发生变化,从而导致使用它的业务域对象也可能要发生变化。
使用Enum作为通用类的属性,制约了该类的通用性。
【注意:】在封闭系统内部是非常适合使用Enum,它会增强代码的可读性,减少维护成本,降低风险。
首先是序列化的风险。
其次Enum增强了系统的耦合性,如果只是接口耦合,那么可以通过WS,HTTP POST等方式来降耦。如果使用了Enum之后,我们进一步增加了对Enum这种特殊类型的处理【大部分标准化协议和现代变成语言,都支持原子类型,对象类型,集合类型,但对Enum的支持却各有所不同】,这就增加了耦合性。此外,此时对于一个使用者要面对多个服务提供者的时候,如果遇到这种情况就会更加痛苦不堪。
再次,Enum在接口层使用,制约了扩展性。当增加一个新的业务常量时,需要修改Enum,此时它的WSDL文件也会发生变化【这点很头痛】,想到于修改了接口描述文件。
最后,我们从业务协议设计的角度来看,我们需要的只是原子数据类型,而不是Enum这么强的一个对象类型。