TL;DR:
DTO 描述了状态转移的模式。 POCO 并没有描述任何东西,只是它没有什么特别之处。这是 OOP 中“对象”的另一种说法。它来自 POJO (Java),由 Martin Fowler 创造,他只是将其描述为“对象”的一个更高级的名称,因为“对象”不是很性感,人们一直在避免它。
扩展中...
好的,以我认为需要的更高级的方式解释这一点,从您最初关于 DTO 的问题开始:
DTO 是一种对象模式,用于在关注层之间传输状态。他们可以有行为(即技术上可以是 poco),只要该行为不会改变状态。例如,它可能有一个序列化自身的方法。
POCO 是一个普通的对象,但“普通”的意思是它不是特殊的,没有任何特定的要求或约定。它只是意味着它是一个没有隐含模式的 CLR 对象。一个通用术语。我还听说它扩展为描述它也不能与其他框架一起使用的事实。因此,例如,如果您的 POCO 在其属性中具有 [JsonProperty] 或 EF 装饰,那么我认为它不是 POCO。 POCO 就像您在学校学习创建的对象一样免费且不受阻碍
这里有一些不同类型的对象模式的示例进行比较:
-
视图模型:用于为视图建模数据。通常有数据注释来帮助绑定和验证特定视图(即通常不是共享对象),或者在当今时代,特定视图组件(例如 React)。在 MVVM 中,它还充当控制器。它不仅仅是一个 DTO;它不是传输状态,而是呈现状态,或者更具体地说,以对 UI 有用的方式形成状态。
-
值对象:用于表示值,应该是不可变的
-
Aggregate Root:用于管理状态和不变量。不应允许通过 ID 以外的方式引用内部实体
-
处理程序:用于响应事件/消息。
-
属性:用作处理横切关注点的装饰。可能只允许在某些对象级别上使用(例如,属性但不是类,方法而不是属性等)
-
服务:用于执行复杂的任务。通常是某种形式的外观。
-
控制器:用于控制请求和响应的流程。通常仅限于特定协议或充当某种调解者;它有特定的责任。
-
工厂:用于配置和/或组装复杂对象,以在构造函数不够好时使用。还用于决定需要在运行时创建哪些对象。
-
Repository/DAO:用于访问数据。通常暴露 CRUD 操作或者是表示数据库模式的对象;可以用实现特定的属性进行标记。事实上,其中一个模式 DAO 对象实际上是另一种 DTO...
-
API 合约:可能会使用序列化属性进行标记。通常需要有公共的 getter 和 setter,并且应该是轻量级的(不是过于复杂的图);与序列化无关的方法并不典型且不鼓励使用。
这些可以被视为只是对象,但请注意,它们中的大多数通常都与模式相关联或具有隐含的限制。所以你可以称它们为“对象”,或者你可以更具体地了解它的意图并用它来称呼它。这也是我们有设计模式的原因;用几句话来描述复杂的概念。 DTO 是一种模式。聚合根是一种模式,视图模型是一种模式(例如 MVC 和 MVVM)。
POCO 没有描述模式。这只是在 OOP 中引用类/对象的一种不同方式,可以是任何东西。将其视为一个抽象概念;他们可以指任何东西。 IMO,这是一种单向的关系,因为一旦一个对象到达它只能干净地服务于一个目的的地步,它就不再是一个 POCO。例如,一旦你用装饰标记你的类以使其与某些框架一起工作(即“插入”它),它就不再是 POCO。因此,我认为有一些逻辑关系,如:
- DTO 是 POCO(直到它被检测)
- POCO 可能不是 DTO
- 视图模型是 POCO(直到它被检测)
- POCO 可能不是视图模型
区分两者的关键在于保持模式清晰一致,以免交叉关注点并导致紧密耦合。例如,如果您有一个业务对象,它具有改变状态的方法,但也使用 EF 装饰装饰到地狱,以保存到 SQL Server 和 JsonProperty,以便可以通过 API 端点将其发送回。该对象将无法容忍更改,并且可能会充斥着各种属性(例如,UserId、UserPk、UserKey、UserGuid,其中一些被标记为不保存到数据库中,而另一些则被标记为不被序列化为API 端点上的 JSON)。
因此,如果您要告诉我某些东西是 DTO,那么我可能会确保它从未用于除了移动状态之外的任何其他用途。如果您告诉我某些东西是视图模型,那么我可能会确保它没有被保存到数据库中。如果你告诉我某个东西是域模型,那么我可能会确保它不依赖于域之外的任何东西。但是,如果您告诉我某物是 POCO,那么您实际上不会告诉我太多,除了它不是也不应该被检测。
历史
从 Fowler 的解释中转述:在一个对象很花哨的世界中(例如,遵循特定的模式、有仪器等),它以某种方式鼓励人们避免使用不花哨的对象来捕获业务逻辑。所以他们给它起了一个花哨的名字POJO。如果您想要一个示例,他所指的是“实体 Bean”,它是具有非常具体的约定和要求等的对象之一。如果您不知道那是什么--> @987654321 @。
相比之下,POJO/POCO 只是您在学校学习创建的常规 ole 对象。