VO和DTO有什么区别?

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是一种设计模式.

歌词大意:

  1. 在调用远程接口时,每一次调用太昂贵.为了减少调用次数,一次调用要尽量多返回点值.
  2. 因为Java这样的语言一次只能返回一个值,所以,创建一个Data Transfer Object来做包装.
  3. 远程接口,所以DTO必须可以序列化.
  4. 通常Server端有一个装配工(assembler)来做域对象(domain objects)DTO之间的转换.
  5. Sun社区(Java的母公司,已死)的人,用Value Object来描述DTO模式
  6. 最后一句说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的主要特点是:

  1. 不可变, final 属性+没有setter 一个构造器就完了
  2. 对应Lombok里的@Value注解
  3. VO可以拿来做Mapkey, 值一样时候hashCode相等,并且equalstrue

Stack Overflow的问答VO和DTO的区别

这个也很精彩,有几个人回答. 歌词大意.

VO和DTO有什么区别?

  1. DTO 是系统的边界
  2. DTO 重在封装
  3. VO 重在相等性
  4. VO 需要不可变

C# Value Object设计模式

这个也是说VO要不可变, 对哈希友好.

C# 的讨论

这个比了一下,DTO,VO,POCO(类似POJO). 歌词大意

VO和DTO有什么区别?

这个更离经叛道, VO带逻辑的.

微软微服务架构教程 中的VO

微软这个书,也提到了VO的特点:

  1. 不可变
  2. 没有identity

DDD

Domain-Driven Design: Tackling Complexity in the Heart of Software

这是本2003年的书.

  1. Entities: Reference Objects
  2. 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 的,
倒是把时间线掰扯清楚了.

  1. 在第一版的《 Core J2EE Patterns》 里, 现在的Data Transfer Object Pattern被错叫成了Value Object Pattern.
  2. 第二版改回来了.
  3. 但是因为已经很流行了,这俩还是被当成同义词

这个锅直接甩给了已经在天国的SUN, 我看了他给的链接,打不开.

不过, 借助时光机 的力量,
我打开了2012年的这个页面.

VO和DTO有什么区别?

好家伙, 这定义, 交换数据, 那可不就是DTO吗?

另外, Adam 这篇文章最好玩的地方倒不是他的文章,而是下面的评论.

有一个叫Chris Martens的用户2011年的评论很有趣, 歌词大意:

  1. DTO 用来传输是对的.
  2. Java EE 的VO也是对的.
  3. 第一版出书时候还没提出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也分为两派:

  1. 一个把VO当成不可变小对象, 类似颜色,性别枚举 这种是一派
  2. 还有一种把不要求小对象, 要求不可变,内部值一样时equals相等.

第二个派别,其实很像Java8的Value-based Classes 概念. 包含今天常用的, Optional, LocalDateTime等不可变类.

我是jkl, 一个抬杠涨了点没用知识的程序员.

上一篇:Spring Boot 系列:Vue+Sping Boot +WebSocket实现前后端消息推送


下一篇:mybatis-plus的多表查询——vo层——@select注解