VO和DTO有什么区别?
你好, 这里是K字的研究.
最近跟人讨论了一会:DTO和VO有没有区别. 我是认为没区别那方.
晚上查了下资料, 发现, 我错了.
TLDR
先说结论,
DTO(Data Transfer Object) 和 VO(Value Object) 两个词, 到底是什么, 从被创造出来的那天,就是混淆的,从来没讨论清楚过. 这两个词,被不同的大佬用来指代各种概念.
以后千万不要参加这种东西的讨论.按照自己组内的分层规范和组内约束来做就行了.跨组不可交流.
文章到这就结束了. 下面是罗列一些我查到的人和他们的说法.
DTO和VO讨论一览
马丁.福勒
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1M1UlhwA-1627611855507)(https://martinfowler.com/img/mf-dallas.jpg)]
首先最容易查到的是Martin Fowler
的看法.
曾经专门写过一篇文章谈Data Transfer Object . 在他这里,DTO
是一种设计模式.
歌词大意:
- 在调用
远程接口
时,每一次调用太昂贵
.为了减少调用次数,一次调用要尽量多返回点值. - 因为Java这样的语言一次只能返回一个值,所以,创建一个
Data Transfer Object
来做包装. - 远程接口,所以
DTO必须可以序列化
. - 通常Server端有一个
装配工(assembler)
来做域对象(domain objects)
和DTO
之间的转换. - Sun社区(Java的母公司,已死)的人,用
Value Object
来描述DTO模式
- 最后一句说JAVA社区管DTO改叫TO了. VO 回归了本意.
还有一篇谈Value Object 的. 他这个比较特殊,管这个叫值对象
, 跟引用对象(Reference Object)做区分. 类似 int, long这种类型,值一样他们就一样,但是本身又是一个Object
.
JEP
JEP 是Java增强提案, OpenJDK官方的正在实现的内容.
在2012年的JEP 169: Value Object 中, 是为了非基础值(不是int,long等值)的类型做高效率值运算做优化引入的内容,主要工作是编译器的.
这个很长, 后面的就不摘了. 看起来主要是做一个非引用Object的优化.
网络教程Value Object
这篇作者就没什么名气了, 不过讲的有点意思. 不过和上面两个有点接近.
在他这里, VO的主要特点是:
- 不可变, final 属性+没有setter 一个构造器就完了
- 对应Lombok里的
@Value
注解 - VO可以拿来做
Map
的key
, 值一样时候hashCode
相等,并且equals
为true
Stack Overflow的问答VO和DTO的区别
这个也很精彩,有几个人回答. 歌词大意.
- DTO 是系统的边界
- DTO 重在封装
- VO 重在相等性
- VO 需要不可变
C# Value Object设计模式
这个也是说VO要不可变, 对哈希友好.
C# 的讨论
这个比了一下,DTO
,VO
,POCO
(类似POJO). 歌词大意
这个更离经叛道, VO带逻辑的.
微软微服务架构教程 中的VO
微软这个书,也提到了VO的特点:
- 不可变
- 没有identity
DDD
Domain-Driven Design: Tackling Complexity in the Heart of Software
这是本2003年的书.
- Entities: Reference Objects
- Value Objects no conceptual identity
An object that represents a descriptive aspect of the domain with no conceptual identity is called a VALUE OBJECT.
VALUE OBJECTS are instantiated to represent elements of the design that we care about only for what they are, not who or which they are.
只关心是什么(what)
, 不关心是谁(who)
和是哪个(which)
.
Adam Bien
一个从java1.0开始用的老用户. 在Oracle发过文章simplicity-by-design .
还有啥我也不知道了. 不过他写过一篇比较DTO VS VO 的,
倒是把时间线掰扯清楚了.
- 在第一版的《 Core J2EE Patterns》 里, 现在的
Data Transfer Object Pattern
被错叫成了Value Object Pattern
. - 第二版改回来了.
- 但是因为已经很流行了,这俩还是被当成同义词
这个锅直接甩给了已经在天国的SUN
, 我看了他给的链接,打不开.
不过, 借助时光机 的力量,
我打开了2012年的这个页面.
好家伙, 这定义, 交换数据, 那可不就是DTO吗?
另外, Adam 这篇文章最好玩的地方倒不是他的文章,而是下面的评论.
有一个叫Chris Martens
的用户2011年的评论很有趣, 歌词大意:
- DTO 用来传输是对的.
- Java EE 的VO也是对的.
- 第一版出书时候还没提出DDD里的VO概念呢.不能拿本朝的剑斩前朝的官
总结
D T O ≠ V O DTO \ne VO DTO=VO
2001年的Java圈曾经用vo
来指代今天被称为dto
的东西.
2003年的DDD
提出了一个VO
.
不知道哪一年, java圈开始用dto
称呼今天的dto
, 但仍保留了vo
的称呼.
在2012年左右,JEP也提出了一个不太一样的Value Object
计划,主要是为了增强值运算的性能.比如如果用对象来实现复数
,那么运算速度会受到方生方死的小对象影响.
现实中对比较正式的VO
也分为两派:
- 一个把
VO
当成不可变小对象, 类似颜色
,性别
枚举 这种是一派 - 还有一种把不要求小对象, 要求不可变,内部值一样时
equals
相等.
第二个派别,其实很像Java8的Value-based Classes 概念. 包含今天常用的, Optional, LocalDateTime等不可变类.
我是jkl, 一个抬杠涨了点没用知识的程序员.