POCO =普通旧CLR(或更好:类)对象
DTO =数据传输对象
在这个post中存在差异,但坦率地说,我读到的大多数博客都以DTO的定义方式描述了POCO:DTO是用于在应用程序层之间移动数据的简单数据容器。
POCO和DTO是一回事吗?
答案 0 :(得分:550)
POCO遵循OOP规则。它应该(但不必)具有状态和行为。 POCO来自POJO,由Martin Fowler [anecdote here]创造。他使用术语POJO作为一种方法,使其更容易拒绝框架繁重的EJB实现。 POCO应该在.Net中使用相同的上下文。不要让框架决定你的对象的设计。
DTO的唯一目的是转移状态,而且应该没有行为。有关使用此模式的示例,请参阅Martin Fowler的explanation of a DTO。
这就是区别: POCO描述了一种编程方法(良好的老式面向对象编程),其中 DTO是一种模式,用于“传输数据”对象。
虽然您可以像对待DTO一样处理POCO,但如果您这样做,则可能会产生anemic domain model。此外,结构不匹配,因为DTO应设计为传输数据,而不是代表业务域的真实结构。结果是DTO往往比实际域更平坦。
在任何合理复杂的领域,您几乎总是更好地创建单独的域POCO并将它们转换为DTO。 DDD(域驱动设计)定义了anti-corruption layer(另一个链接here,但最好的办法是buy the book),这是一个很好的结构,可以清除隔离。
答案 1 :(得分:49)
由于我已在博客文章中说明了自己的立场,因此对我来说可能是多余的,但该文章的最后一段总结了一些内容:
所以,最后,学会爱POCO,并确保你不会传播任何与DTO相同的错误信息。 DTO是用于在应用程序层之间移动数据的简单数据容器。 POCO是完全成熟的业务对象,其中一个要求是Persistence Ignorant(无get或save方法)。最后,如果你还没有查看Jimmy Nilsson的书,请从你当地的大学校园里拿出来。它有C#中的示例,这是一个很好的阅读。
顺便说一句,帕特里克我读过POCO作为一篇生活方式的文章,我完全同意,这是一篇很棒的文章。这实际上是我推荐的吉米尼尔森书中的一部分。我不知道它是否可以在线获取。他的书确实是我在POCO / DTO / Repository /和其他DDD开发实践中发现的最佳信息来源。答案 2 :(得分:27)
POCO只是一个不依赖于外部框架的对象。这是普拉。
POCO是否有行为是无关紧要的。
DTO可能是POCO,也可能是域对象(通常会有丰富的行为)。
通常,DTO更可能依赖外部框架(例如属性)进行序列化,因为它们通常会在系统边界处退出。
在典型的洋葱风格体系结构中(通常在广泛的DDD方法中使用),域层位于中心,因此其对象在此时不应具有该层之外的依赖关系。
答案 3 :(得分:14)
答案 4 :(得分:6)
我认为DTO可以是POCO。 DTO更多地是关于对象的使用,而POCO更像是对象的风格(与架构概念分离)。
POCO与DTO不同的一个例子是当你在域模型/业务逻辑模型中讨论POCO时,这是你问题域的一个很好的OO表示。您可以在整个应用程序中使用POCO,但这可能会产生一些不良副作用,例如知识泄漏。例如,DTO是从与UI通信的服务层使用的,DTO是数据的平面表示,并且仅用于向UI提供数据,并且将更改传送回服务层。服务层负责将DTO的两种方式映射到POCO域对象。
更新 Martin Fowler said这种方法很难走,只有在域层和用户界面之间存在严重不匹配时才应采取这种做法。
答案 5 :(得分:2)
这是一般规则:DTO ==邪恶和过度设计软件的指标。 POCO ==好。 “企业”模式已经破坏了Java EE世界中许多人的大脑。请不要重复.NET land中的错误。
答案 6 :(得分:1)
DTO的主要用例是从Web服务返回数据。在这种情况下,POCO和DTO是等价的。当从Web服务返回时,POCO中的任何行为都将被删除,因此它是否具有行为并不重要。
答案 7 :(得分:0)
TL; DR:
DTO描述状态转移的模式。 POCO没有描述任何内容。这是在OOP中说“对象”的另一种方式。它来自由马丁·福勒(Martin Fowler)创造的POJO(Java),他实际上只是将其描述为“对象”的昵称,因为“对象”不是很性感。
DTO是一种对象模式,用于在相关层之间转移状态。他们可以有行为(即从技术上讲可以是poco),只要该行为不会改变状态即可。例如,它可能具有一种自行序列化的方法。
POCO是一个普通的对象,但是“普通”的含义是它并不特殊。这只是意味着它是一个CLR对象,没有隐式模式。通用术语。它不是与其他框架一起使用的。因此,例如,如果您的POCO的所有属性都具有[JsonProperty]
或EF装饰,那么我认为它不是POCO。
下面是一些不同类型的对象模式的示例,以进行比较:
这些都是对象,但是请注意,大多数对象通常都与模式相关。因此,您可以将它们称为“对象”,也可以更具体地说明其意图,并按其含义进行称呼。这也是我们拥有设计模式的原因。在一些作品中描述复杂的概念。 DTO是一种模式。聚合根是一种模式,视图模型是一种模式(例如MVC和MVVM)。 POCO不是模式。
POCO没有描述模式。这只是在OOP中引用类/对象的另一种方式。将其视为一个抽象概念;他们可以指任何东西。 IMO,这是一种单向关系,因为一旦对象到达只能清洁地用于一个目的的位置,它就不再是POCO。例如,一旦用装饰标记了您的类以使其可以在某些框架上使用,则它不再是POCO。因此:
在两者之间进行区分的重点是保持模式清晰一致,以免引起关注并导致紧密耦合。例如,如果您有一个具有更改状态方法的业务对象,但还使用EF装饰修饰到地狱,以保存到SQL Server和JsonProperty,以便可以通过API端点发送回该对象。该对象将不能容忍更改,并且可能会被各种属性(例如,UserId,UserPk,UserKey,UserGuid)填充,其中一些标记为不保存到数据库,而另一些标记为不序列化到API端点处的JSON)。
因此,如果您要告诉我某事是DTO,那么我可能会确保除了移动状态外,它从未被用于其他任何用途。如果您告诉我某些东西是视图模型,那么我可能会确保它没有保存到数据库中。如果您告诉我某些东西是域模型,那么我可能会确保它不依赖于域之外的任何东西。但是,如果您告诉我某事是POCO,那么您根本不会告诉我太多。
答案 8 :(得分:-14)
甚至不称他们为DTO。他们称之为模型 ....期间。模特永远不会有行为。我不知道是谁想出了这个愚蠢的术语DTO,但它必须是.NET的东西才是我能想到的。想想MVC中的视图模型,同样的坝**事物,模型用于在服务器端层或线路周期之间传输状态,它们都是模型。包含数据的属性。这些是你通过电线传递的模型。型号,型号型号。就是这样。
我希望DTO这个愚蠢的词语能够脱离我们的词汇量。