【IT168 资讯】 在Amber项目中,有一份关于Java“数据类”的新建议草案,笔者总结了以下几个要点:
1. 设计意图:明确无误地表达一个类作为 “DTO”的设计意图;
2. 样板:让编译器负责像equals()和hashCode()这样的典型DTO一样来操作;
3. Switch语句:简要介绍了在DTO周围启用语义特征,能够将它们用作switch语句的目标;
该草案还涉及到一些具体的细节,如访问者不必遵循JavaBeans约定、选择可变性和迁移/兼容性等问题。
笔者通过分析以下几点,为大家解释不看好这个提案的原因。
设计意图
这是一个很有价值的目标:读者将立即明白数据类的设计意图,不必通过典型的getter、setter、equals、hashCode和toString来实现遍历,以确保该类只有一个数据类。
退一步问:在项目中定义了多少DTO类型,这种新的语言结构是否会大大简化代码?如果这两个问题的答案都是“很多”,那么就有了一个更深层次的问题,这个新构造不能解决的问题:可能没有以面向对象的方式来思考问题。所定义的许多类型只是数据的一部分,而且很可能是用命令式的方式编程。这是笔者的论点的根结所在。DTO是一个反模式,但纯粹的OOP是不实际的,因此,没有必要去纠结。
是的,DTO有时是不可避免的,尤其是在与远程API(例如JAX-WS)接口时。但是,有几点:
* 这些都应该存在于代码的外围;
* 它们应该被域模型封装,其中有类似于equals()和hashCode()的重要方法;
DTO如果存在的话,应该只存在于项目的边缘,而不是整个设计理念的主干。理想情况下,它们应该只有在像wsimport这样的框架/工具自动生成时才存在。
样板
如果接受了前面的论点,那么getter / setter“样板”就不存在争论:工具只会在需要的地方自动创建。关于需要注意的其他Object方法:equals()和hashCode(),笔者有一些自己的想法:
*它们应该被从Object中取出,并且进入它们自己的接口;
*并不是所有的API都需要所有的DTO来实现equals(),更不必说hashCode();
Switch语句
可能是由于性能或者其他问题,没使用Object#equals打开任何对象。一个SO用户表达了自己观点:“...技术障碍不应该推动语言设计。如果没有办法将它编译成高效的代码,它仍然可能被编译成if ... else ...子句的等价形式,仍然有源代码简洁的优点”。