DTO的组成部分也是实体或DTO
本文关键字:DTO 实体 组成部分 | 更新日期: 2023-09-27 18:28:53
我有术语问题。根据Fowler的说法,DTO是"一个在进程之间传递数据以减少方法调用次数的对象。"(http://martinfowler.com/eaaCatalog/dataTransferObject.html)。据我所知,减少方法调用的唯一方法是将它们联合起来。所以DTO是一个复合对象,包含一些实体。
例如,我们有两个简单的实体CoinInfo和ProductInfo:
public class CoinInfo
{
public int CoinId { get; set; }
public int Denomination { get; set; }
public int Quantity { get; set; }
}
public class ProductInfo
{
public int ProductId { get; set; }
public ProductTypes ProductType { get; set; }
public int Price { get; set; }
public int Count { get; set; }
}
我们还有一个复杂的对象SomeDto,它将CoinInfo和ProductInfo结合在一起。
public class SomeComplex
{
public List<CoinInfo> UserWallet { get; set; }
public List<ProductInfo> Products { get; set;}
}
那么,ProductInfo和CoinInfo是"DTO"还是仅仅是"实体"?
当您跨越类、组件或应用程序边界时,数据传输对象就会发挥作用。使用DTO可以减少类、组件或应用程序之间的耦合。
例如,当构建要由客户端使用的服务时,您可能需要引入三个组件:
- 服务:包含业务逻辑,也许还有一些服务托管样板(尽管您通常希望在自己的项目中提供最后一点)
- 客户端库:应用程序可以用来调用服务中的方法
- 数据传输对象:服务和客户端都引用这些对象
现在,希望与该服务通信的客户端应用程序只需要引用客户端库和DTO库。您的服务使用哪些其他类型来发挥其魔力对客户端来说根本不感兴趣,应该保持隐藏。
现在DTO的要点是使用它们来为API建模。您可以决定从服务中公开的内容以及这些数据的外观。您可以选择合成,将较小的DTO聚合为较大的DTO,如图所示。
您需要记住的是不要通过DTO公开服务内部。您使用的是"实体"一词,这让我觉得您试图公开,例如,在DTO中聚合的实体框架模型。你不应该这样做。这样做是在创建一个"泄漏抽象",使更改数据库(添加或删除列,替换ORM,…)和更改服务返回的信息(添加或移除属性,…)变得更加困难。除此之外,使用实体框架模型作为DTO会带来大量分配、延迟加载和循环引用的问题,所有这些都需要解决方法。
您可以使用属性来解决这些潜在的问题,让ORM或服务序列化程序忽略那些无关的属性,但这些仍然是解决方案。如果你真的需要公开看起来很像你的数据模型的DTO,那么引入映射(例如使用AutoMapper):
- 服务。数据:包含"实体"
- 服务:将"实体"映射到DTO,并返回/接受后者
- 客户端库:仍然只看到并需要引用DTO
在这个场景中,服务的数据层和从服务返回的模型是解耦的。
如果所有这些都不是你关心的,而是命名法:是的,你显示的所有三个类都是DTO。
由于CoinInfo
和ProductInfo
也适合执行CRUD(即创建、读取、更新、删除)操作,我认为关联根及其自身的关联也是DTO。
当你问这些类是否是实体时,这取决于你对的理解。如果你想知道它们是否是域对象,除非你在域中使用它们,否则它们就不是,毕竟这会破坏使用DTO模式的目的。
DTO最适合使用立面,因为它们不一定与域绑定,因为它们只是简化域或任何其他层的接口(这将取决于立面的实现)。也就是说,DTO应该是向立面输入和从立面输出数据的最佳选择。
换句话说:你不应该跨越物理边界输出域对象,因为域对象可能包含太多信息,这可能会浪费数据传输,而且你可能会将私有的数据暴露给域,而不应该为整个域的消费者所知。
DTO扮演自己的角色,只映射需要暴露在实际域顶部的层中的数据。此外,有时域对象包含无用的数据,这些数据可以序列化/反序列化并恢复整个对象的有效状态(它们可能与数据连接有一些关联:想想分别与域上下文或会话关联的实体框架或NHibernate代理……这只是一个例子,还有很多其他)。
我对DTO的理解是,它们在Android中扮演着与"parcelable"非常相似的角色(这也要求成员变量是parcelable的(本地类型或直接实现parcelable接口)。
Parcelable用于跨越进程边界(IPC),DTO是一种稍微宽泛的模式。(用于IPC、客户端/服务器通信等)(以便解释什么是"可分组",以及DTO有何不同)
DTO看起来有相同的层次结构,DTO中的所有内容都必须是可串行的(尽管它看起来不需要像安卓系统中那样实现一些特定的接口),所以我想说这三个都是DTO。只是有些比其他更复杂。
值得一提的是,另一个优点是封装用于通过导线传输数据的串行化机制。通过像这样封装序列化,DTO保持这个逻辑剩余的代码
从您的链接
Parcelable-要求-在类中包含序列化代码。而DTO只是一种很好的做法(我不认为是必需的)
(很抱歉进行了如此多的android比较,我希望比较/对比有帮助)