普通的旧CLR对象与数据传输对象

POCO =普通旧CLR(或更好:Class)对象

DTO =数据传输对象

在这篇文章中有一个区别,但是坦率地说,我读过的大多数博客都以定义DTO的方式描述了POCO:DTO是用于在应用程序各层之间移动数据的简单数据容器。

POCO和DTO是同一件事吗?


#1楼

POCO只是一个不依赖外部框架的对象。 是平原。

POCO是否具有行为无关紧要。

DTO可能是POCO,领域对象也可能是POCO(通常行为丰富)。

通常,DTO更有可能出于序列化目的而依赖于外部框架(例如,属性),因为它们通常会在系统边界处退出。

在典型的Onion风格的体系结构(通常在广泛的DDD方法中使用)中,域层位于中心,因此此时其对象不应在该层之外具有依赖关系。


#2楼

甚至不称它们为DTO。 他们被称为模型 ...。 模型永远不会有行为。 我不知道是谁提出了这个愚蠢的术语DTO,但我能弄清楚它一定是.NET。 考虑一下MVC中的视图模型,同样重要的是,模型用于在服务器层之间或整个线路周期之间传输状态,它们都是模型。 带有数据的属性。 这些是您通过电线的模型。 模型,模型模型。 而已。

我希望愚蠢的术语“ DTO”能摆脱我们的词汇量。


#3楼

我为该主题写了一篇文章: DTO vs Value Object vs POCO

简而言之:

  • DTO!=值对象
  • DTO⊂POCO
  • 值对象⊂POCO

#4楼

DTO类用于对来自不同来源的数据进行序列化/反序列化。 当您想从源中反序列化对象时,与服务,文件,数据库等外部源无关,您可能只想使用其中的一部分,但是您想要一种简单的方法将数据反序列化为对象。宾语。 之后,将数据复制到要使用的XModel。 串行器是一种加载DTO对象的漂亮技术。 为什么? 您只需要一个函数即可加载(反序列化)对象。


#5楼

TL; DR:

DTO描述了状态转移的模式。 POCO没有描述任何内容。 这是在OOP中说“对象”的另一种方式。 它来自由马丁·福勒(Martin Fowler)创造的POJO(Java),实际上,它只是将其描述为“对象”的更奇特的名字,因为“对象”不是很性感。

DTO是一种对象模式,用于在相关层之间转移状态。 他们可以有行为(即从技术上讲可以是poco),只要该行为不会改变状态即可。 例如,它可能具有序列化自身的方法。

POCO是一个普通的对象,但是“普通”的含义是它并不特殊。 这只是意味着它是一个CLR对象,没有隐式模式。 通用术语。 它不是与其他框架一起使用的。 因此,例如,如果您的POCO的所有属性都具有[JsonProperty]或EF装饰,那么我会认为它不是POCO。

这里有一些不同种类的对象模式的例子进行比较:

  • 视图模型 :用于为视图数据建模。 通常具有数据注释以帮助绑定和验证。 在MVVM中,它还充当控制器。 不仅仅是DTO
  • 值对象 :用于表示值
  • 聚合根 :用于管理状态和不变式
  • 处理程序 :用于响应事件/消息
  • 属性 :用作装饰来处理横切关注点
  • 服务 :用于执行复杂的任务
  • 控制器 :用于控制请求和响应的流程
  • 工厂 :用于配置和/或组装复杂的对象,以在构造函数不够好时使用。 还用于确定在运行时需要创建哪些对象。
  • 存储库/ DAO :用于访问数据

这些都是对象,但请注意,它们中的大多数通常与某个模式相关联。 因此,您可以将它们称为“对象”,也可以更具体地说明其意图,并按其含义进行称呼。 这也是我们拥有设计模式的原因。 在一些作品中描述复杂的概念。 DTO是一种模式。 聚合根是一个模式,视图模型是一个模式(例如MVC和MVVM)。 POCO不是模式。

POCO没有描述模式。 这只是在OOP中引用类/对象的另一种方式。 将其视为一个抽象概念; 他们可以指任何东西。 IMO,这是一种单向关系,因为一旦对象到达只能清洁地用于一个目的的位置,它就不再是POCO。 例如,一旦用装饰标记了您的类以使其可以在某些框架上使用,则它不再是POCO。 因此:

  • DTO是POCO
  • POCO不是DTO
  • 视图模型是POCO
  • POCO不是视图模型

区分两者的重点在于保持模式清晰一致,以免引起关注并导致紧密耦合。 例如,如果您有一个具有更改状态方法的业务对象,但还使用EF装饰修饰到地狱,以保存到SQL Server和JsonProperty,以便可以通过API端点发送回该对象。 该对象将不能容忍更改,并且可能会被各种属性(例如,UserId,UserPk,UserKey,UserGuid)填充,其中一些标记为不保存到数据库,而另一些标记为不序列化到API端点处的JSON)。

因此,如果您要告诉我的是DTO,那么我可能会确保除了将状态转移之外,它从未被用于其他任何用途。 如果您告诉我某些东西是视图模型,那么我可能会确保它没有保存到数据库中。 如果您告诉我某些东西是域模型,那么我可能会确保它不依赖于域之外的任何东西。 但是,如果您告诉我某事是POCO,那么您根本不会告诉我太多。


#6楼

POCO遵循OOP规则。 它应该(但不是必须)具有状态行为。 POCO来自POJO,由Martin Fowler [杜撰故事在这里 。 他使用术语POJO来使拒绝框架繁重的EJB实现更加性感。 POCO应该在.Net中的相同上下文中使用。 不要让框架决定对象的设计。

DTO的唯一目的是转移状态,并且不应有任何行为。 有关使用此模式的示例,请参见Martin Fowler 对DTO解释

区别在于: POCO描述了一种编程方法 (老式的面向对象编程),其中DTO是一种用于使用对象“传输数据” 的模式

虽然您可以将POCO像DTO一样对待,但是这样做会冒创建贫血域模型的风险。 此外,由于DTO应该被设计为传输数据,而不是代表业务域的真实结构,因此结构上存在不匹配。 这样的结果是DTO往往比您的实际域平坦。

在任何合理复杂性的域中,几乎总是最好创建单独的域POCO并将其转换为DTO。 DDD(域驱动设计)定义了反腐败层此处是另一个链接,但最好的办法是购买书 ),这是一个很好的结构,可以使隔离清晰。


#7楼

我认为DTO可以是POCO。 DTO更多关于对象的使用,而POCO更多关于对象的样式(与体系结构概念脱钩)。

当您在域模型/业务逻辑模型中谈论POCO时,POCO与DTO有所不同的一个例子是,它很好地表示了您的问题域。 您可以在整个应用程序中使用POCO,但这可能会带来一些不良的副作用,例如知识泄漏。 例如,DTO是从与UI进行通信的服务层使用的,DTO是数据的平面表示,并且仅用于为UI提供数据,并将更改传达回服务层。 服务层负责将DTO的两种方式映射到POCO域对象。

Update Martin Fowler ,这种方法是繁重的,只有在域层和用户界面之间存在重大不匹配的情况下,才应采用这种方法。


#8楼

DTO的主要用例是从Web服务返回数据。 在这种情况下,POCO和DTO是等效的。 从Web服务返回POCO时,POCO中的任何行为都将被删除,因此,是否具有行为并不重要。


#9楼

这是一般规则:DTO ==邪恶和过度设计的软件的指示器。 POCO ==好。 “企业”模式破坏了Java EE世界中许多人的大脑。 请不要在.NET land中重复该错误。


#10楼

因为我已经在博客文章中表达了自己的立场,所以对我来说可能是多余的,但是该文章的最后一段总结了这一点:

因此,总而言之,学习爱POCO,并确保您不会散布任何与DTO相同的错误信息。 DTO是简单的数据容器,用于在应用程序的各层之间移动数据。 POCO是成熟的业务对象,其一个要求是持久性忽略(没有获取或保存方法)。 最后,如果您还没有签出吉米·尼尔森(Jimmy Nilsson)的书,请从您当地的大学图书馆中取书。 它具有C#中的示例,并且读起来很不错。

顺便说一句,帕特里克·帕特里克(Patrick)我读了POCO的《生活方式》一文,我完全同意,那是一篇很棒的文章。 实际上,这是我推荐的Jimmy Nilsson书中的一部分。 我不知道它可以在线获得。 他的书确实是我在POCO / DTO /存储库/和其他DDD开发实践中找到的最佳信息来源。

发布了0 篇原创文章 · 获赞 2 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/asdfgh0077/article/details/104235770