简体   繁体   English

域对象构建DTO的设计

[英]design of building DTO from domain object

I have a graph of domain objects and i need to build a DTO to send it to the view. 我有一个域对象图,我需要构建一个DTO才能将其发送到视图。 How to design it properly? 如何正确设计? I see 2 options where can I put the DTO building code: 我看到两个选项,可以在其中放置DTO构建代码:

1) Into the DTO constructor. 1)进入DTO构造函数。 But then the domain object has to present all fields to DTO via getters so it's not a DDD. 但是,然后域对象必须通过getter将所有字段呈现给DTO,因此它不是DDD。

public DTO(DomainObject domain) {
   /// access internal fields of different domain object.
}

2) Into the domain object. 2)进入域对象。 There will be no problem with accessing fields but the domain object will grow very fast when new view are added. 访问字段不会有任何问题,但是添加新视图时,域对象会非常快地增长。

public DTO1 createDTO1() {
    ...
}

public DTO2 createDTO1() {
    ...
}

// and so on...

How should I build DTOs properly? 我应该如何正确构建DTO?

I think there is a bigger issue at play here. 我认为这里有一个更大的问题。 You should not be querying your domain. 应该查询您的域。 Your domain should be focused on behaviour and, as such, will quite possibly not contain the data in a format suitable for a view, especially for display purposes. 您的域应专注于行为,因此,很可能将不包含适用于视图(尤其是用于显示目的)的格式的数据。

If you are sending back your entire, say, Customer object to Edit then you are performing entity-based interactions that are very much data focused. 如果您要将整个(例如, Customer对象发回给Edit则您正在执行基于实体的交互,这些交互非常注重数据。 You may want to try and place more attention on task-based interactions. 您可能想尝试将更多的注意力放在基于任务的交互上。

So to get data to your view I'd suggest a simple query layer. 因此,为了获得数据到您的视图,我建议使用一个简单的查询层。 Quite often you will need some denormalized data to improve query performance and that will not be present in your domain anyway. 通常,您将需要一些非规范化的数据以提高查询性能,而这些数据无论如何都不会出现在您的域中。 If you do need DTOs then map them directly from your data source. 如果确实需要DTO,则直接从数据源映射它们。 If you can get away with a more generic data container structure then that is first prize. 如果您可以使用更通用的数据容器结构,那将是头等大事。

Variants: 变体:

  1. Constructor with simple types in DTO: public DTO(Long id, String title, int year, double price) DTO中具有简单类型的构造方法:public DTO(长ID,字符串标题,整数年,双倍价格)
  2. Separate class - converter with methods like: DTO1 createDTO1(DomainObject domain) 单独的类-具有以下方法的转换器:DTO1 createDTO1(DomainObject域)
  3. Framework for copy properties from one object to other, like Dozer: http://dozer.sourceforge.net/ 用于将属性从一个对象复制到另一个对象的框架,例如Dozer: http : //dozer.sourceforge.net/

1) ... the domain object has to present all fields to DTO via getters ... 1)...域对象必须通过getter将所有字段呈现给DTO ...

2) ... the domain object will grow very fast ... 2)...领域对象将增长非常快...

As you can see, the problem is that both alternatives are coupling your model with your DTOs, so you need to decouple them: introduce a layer between them in charge of performing the mapping/translation. 如您所见,问题在于这两种选择都将您的模型与DTO耦合在一起,因此您需要将它们分离:在它们之间引入一个层来执行映射/转换。

You may find this SO question useful. 您可能会发现此SO问题很有用。

domain object has to present all fields to DTO via getters so it's not a DDD 域对象必须通过getter将所有字段呈现给DTO,所以它不是DDD

Just because a domain object has getters doesn't make it anemic or anti-DDD. 仅由于域对象具有吸气剂,并不能使其成为贫血或抗DDD。 You can have getters and behavior. 你可以有吸气剂行为。

Besides, since you want to publish to the View a DTO containing particular data, I can't see how this data can remain private inside the domain object. 此外,由于您要向View 发布包含特定数据的DTO,因此我看不到该数据如何在域对象内保持私有状态。 You have to expose it somehow. 您必须以某种方式公开它。

Solution 2) breaks separation of concerns and layering (it's not a domain object's business to create a DTO) so I'd stick with 1) or one of @pasha701's alternatives. 解决方案2)打破了关注点和层次的分离(创建DTO不是域对象的事,所以我坚持使用1)或@ pasha701的替代方法之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM