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.
Put the classes close to where they're actually used. Show activity on this post. In your case,the DTO is accessed by both Presentation & Domain. so better to have it Infrastructure and refer it from there.
In order to implement DTO, let's create a Spring Boot application that exposes REST API. By using that Spring Boot application, we can retrieve the user locations from an H2 database. For implementing that application, we should have knowledge of how to integrate the H2 database with Spring Boot.
DTO, which stands for Data Transfer Object, is a design pattern conceived to reduce the number of calls when working with remote interfaces. As Martin Fowler defines in his blog, the main reason for using a Data Transfer Object is to batch up what would be multiple remote calls into a single one.
A DTO may be used to: Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.
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 would say it's better to create DTO on Service layer.
Controller must not know business logic details. E.g. 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With