我最近听到人们说data transfer objects(DTO)是反模式。
为什么呢?有哪些替代方案?
答案 0 :(得分:121)
有些项目的所有数据都是两次。一旦作为域对象,一次作为数据传输对象。
这种重复成本很高,因此架构需要从这种分离中获得巨大收益才值得。
答案 1 :(得分:117)
DTO不是反模式。当您通过网络发送一些数据(例如,通过Ajax调用中的网页)时,您希望通过仅发送目标将使用的数据来确保节省带宽。此外,表示层通常可以方便地使数据的格式与本机业务对象略有不同。
我知道这是一个面向Java的问题,但在.NET语言中,匿名类型,序列化和LINQ允许在运行中构建DTO,这减少了使用它们的设置和开销。
答案 2 :(得分:22)
DTO an AntiPattern in EJB 3.0说:
实体的重量级特性 EJB规范之前的Bean EJB 3.0导致了使用 设计模式,如数据传输 对象(DTO)。 DTO成为了 轻量级对象(应该有 是实体豆本身 第一个地方),用于发送 跨层的数据......现在是EJB 3.0 spec使Entity bean模型相同 作为普通的旧Java对象(POJO)。同 这个新的POJO模型,你不会 需要为每个人创建一个DTO 实体或一组实体......如果 您想发送EJB 3.0实体 整个层面使他们只是 实现java.io.Serialiazable
答案 3 :(得分:17)
我不认为DTO本身就是一种反模式,但是有一些与使用DTO相关的反模式。 Bill Dudney以DTO爆炸为例:
http://www.softwaresummit.com/2003/speakers/DudneyJ2EEAntiPatterns.pdf
此处提到的DTO也有许多滥用行为:
http://anirudhvyas.com/root/2008/04/19/abuses-of-dto-pattern-in-java-world/
它们起源于三层系统(通常使用EJB作为技术)作为在层之间传递数据的手段。基于Spring等框架的大多数现代Java系统在单层中使用POJO作为域对象(通常用JPA等注释......)采用另一种简化视图......这里不需要使用DTO。
答案 4 :(得分:13)
答案 5 :(得分:7)
有些人认为DTO是一种反模式,因为它们可能存在滥用行为。它们经常在它们不应该/不需要的时候使用。
This article模糊地描述了一些滥用行为。
答案 6 :(得分:6)
如果您正在构建分布式系统,那么DTO肯定不是反模式。不是每个人都会在这个意义上发展,但如果你有一个(例如)Open Social应用程序都运行JavaScript。
它会向您的API发布大量数据。然后将其反序列化为某种形式的对象,通常是DTO / Request对象。然后可以对其进行验证,以确保在转换为模型对象之前输入的数据是正确的。
在我看来,它被视为一种反模式,因为它被误用了。如果您不构建分布式系统,则可能不需要它们。
答案 7 :(得分:3)
Data Transfer Object的意图是存储来自不同来源的数据,然后立即将其传输到数据库(或Remote Facade)。
然而, DTO模式违反了Single Responsibility Principle ,因为DTO不仅存储数据,还将数据传输到数据库/外观。
将数据对象与业务对象分开的需要不是反模式,因为无论如何它可能都需要separate the database layer。
您应该使用聚合和存储库模式来代替DTO,这些模式分隔对象集合(Aggregate)和数据传输(Repository)。
要传输一组对象,您可以使用Unit Of Work模式,该模式包含一组存储库和事务上下文;为了在事务中单独转移聚合中的每个对象。
答案 8 :(得分:3)
如果您不制作DTO,则会有从业务层到客户/网络层的不必要转移的对象。
限制此情况的开销,而不是转移DTO。
答案 9 :(得分:1)
问题不应该是“为什么”,而应该是“ 何时”。
绝对是反模式,只有使用它的结果是更高的成本-运行时或维护。我从事的项目具有与数据库实体类相同的数百个DTO。每次您要添加一个字段时,您的广告都会向IDTO添加四倍的ID-到DTO,到实体,从DTO到领域类或实体的转换,逆向转换... ...您忘记了获得的一些位置和数据不一致的。
当您确实需要域类的不同表示形式时,这不是反模式-更平坦,更丰富,更狭窄,...
我个人从域类开始,并在正确的位置进行适当的检查,然后将其传递。我可以注释和/或添加一些“帮助程序”类,以进行映射,数据库,序列化格式(如JSON或XML)……如果需要,我总是可以将一个类拆分为两个。
这是关于您的观点的-我更喜欢将域对象视为扮演各种角色的单个对象,而不是彼此创建的多个对象。如果对象唯一的角色是传输数据,则为DTO。
答案 10 :(得分:0)
我认为,如果您将所有远程对象实现为DTO,那么人们就意味着它可能是一种反模式。 DTO只是一组属性,如果您有大对象,即使您不需要或使用它们,也总是会传输所有属性。在后一种情况下,更喜欢使用代理模式。