Trying to refactor some code. I see some classes creating DTO objects which are being passes in the service layer and returned later by the @RestController. As I know it is best to build the Data Transfer Objects only in the controllers and pass them to the views, especially when we use something like WrapperDTO<T>
with get and set value. Maybe there are differences when we are building the WrapperDTO with complex object or simple data types. All oppinions will be well appreciated.
DTO may be used to transfert data between the different layers of an application: DAO, Service, Facade, Controller. In my experience DTO is an opinionated topic.
In my opinion, the later the conversion, the better, it is even better if no conversion is needed. Generally, the later is at the application boundary. DTO is not free, it involves mapping and its support. Hence DTOs will make sense when there is a domain model mismatch or a model technical mismatch accross the boundary. For more information you can have a look at LocalDTO article and the associated link .
If I focus on the service -> facade -> controller layers:
Services: They are doing services things and they may call each other to do their processing. If your domain models remain consistent across the services boundary service => facade
it is too early to convert the result into a DTO.
Facades: They may orchestrate services and convert input/output. In my point of view it will be the right place to convert to or from DTO. But only if it is needed to ie. because your domain models have to be transformed accross this boundary (filtering fields, aggregation...)
Gateway/Controllers: They are at the application boundary. Their logics are simple, reduced to the boundary logic. The relation between a facade and a controller is usually one <-> one
. ***
Merging facades and controllers usually make sense
Thus in my point of view, your first proposal is more adapted eg. UserController....
. The most important is to stay pragmatic.
I would say it's better to create DTO on Service layer.
Controller must not know business logic details. Eg we need to return User info but some fields (password etc.) must be excluded. The fields exist in the User entity but must be removed from DTO.
Another case we got SomePaginationDTO
on Controller and we still need to pass the DTO to service to parse filter, apply sort, limit results etc. All the logic is part of service responsibility. So I would pass the SomePaginationDTO
to service.
I would say there is no canonically right way to do this. It depends on what is DTO used for.
I found a simple rule for myself on where to use DTO in service level and where to not: In case if service level has only one client I use DTO across service level. In case if there are two or more clients it is better not to use DTO in service level.
Let me explain this in more details:
Basically it is clear that not including DTO into service level requires more efforts. So in case if there is only one client I would keep things simple and use DTO as a return type for service methods.
In case if there are more then one client of the service most likely the clients will require different DTO (for instance I want to have json
and csv
representation of an object). In such case I will not return DTO from service. Otherwise I would need to have different services for each DTO, or different service methods, etc.
Note: I'm not saying that if you don't use DTO in service level you must move the transformation logic into controller level. I still think that controller level must be as simple as possible. You might have some intermediate transformation level between controller and service - uncomfortable, but it is much better then having several services.
I found a great answer as a part of other question. Of course this/my answer does not participate for the bounty. It is just an inspiration someone to explain how the things are implemented nowadays. So take a look:
What do you think about that design? Is it applicable for the well know spring mvc?
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.