简体   繁体   中英

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. How to design it properly? I see 2 options where can I put the DTO building code:

1) Into the DTO constructor. But then the domain object has to present all fields to DTO via getters so it's not a DDD.

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

2) Into the domain object. 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?

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. 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. 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)
  2. Separate class - converter with methods like: DTO1 createDTO1(DomainObject domain)
  3. Framework for copy properties from one object to other, like Dozer: http://dozer.sourceforge.net/

1) ... the domain object has to present all fields to DTO via getters ...

2) ... the domain object will grow very fast ...

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.

You may find this SO question useful.

domain object has to present all fields to DTO via getters so it's not a DDD

Just because a domain object has getters doesn't make it anemic or anti-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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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