DTO Data Transfer Object Where to Build
An attempt was made to refactor the code. I see that some classes create DTO objects that go through the service layer and are later returned by @RestController. As I know it is best to only create data transfer objects in controllers and pass them to views, especially when we use something like WrapperDTO<T>
with get and set value. There may be differences when we create WrapperDTO with complex object or simple data types. All opponents will be well appreciated.
source to share
DTO can be used to transfer data between different layers of the application: DAO, Service, Facade, Controller. In my experience, DTOs are a stubborn topic.
In my opinion, the later the conversion, the better, even better if the conversion is not required. Typically, the later version is at the application boundary. The DTO is not free, it includes display and support. Hence, DTOs will make sense if there is a domain model mismatch or model model mismatch along the boundary. For more information, you can look at the LocalDTO article and related link .
If I focus on service layers -> facade -> controller:
-
Services: They perform services and they can call each other to complete their processing. If your domain models remain consistent across the service boundary
service => facade
, it's too early to convert the result to DTOs. -
Facades: They can organize services and transform I / O. From my point of view, this would be a good place to convert to or from DTOs. But only if it is necessary for that is. because your domain models need to be transformed along that boundary (filter fields, aggregation ...)
-
Gateway / Controllers: These are at the application boundary. Their logic is simple, reduced to boundary logic. The communication between the facade and the controller is normal
one <-> one
. ***Merging facades and controllers usually makes sense
So from my point of view, your first sentence is more adapted, eg. UserController....
... The most important thing is to remain pragmatic.
source to share
I would say that it is better to create the DTO at the service level.
The controller does not need to know the details of the business logic. For example. we need to return information about the user, but some fields (password, etc.) should be excluded. The fields exist in the User object, but must be removed from the DTO.
In another case, we got SomePaginationDTO
on the controller and we still need to pass a DTO to service the parse filter, apply sorting, limit results, etc. All logic is part of the service responsibility. So I handed over SomePaginationDTO
for service.
source to share
I would argue that there is no canonically correct way to do this. It depends on what the DTO is used for.
I found a simple rule for myself about where to use DTOs at the service level and where not: In case there is only one client at the service level, I use DTOs through the service level. If there are two or more clients, it is best not to use DTOs at the service level.
Let me explain this in more detail:
In principle, it is clear that not including DTOs in the service level requires more effort. So in case there is only one client, I would simplify and use DTO as the return type for the service methods.
In case there is more than one client of the service, chances are the clients will need different DTOs (for example, I want to have a view json
and an csv
object). In such a case, I will not return a DTO from the service. Otherwise, I will need to have different services for each DTO, or different service methods, etc.
Note. I am not saying that if you are not using DTOs in the service layer, you should move your transformation logic to the controller layer. I still think the controller layer should be as simple as possible. You can have some intermediate level of transformation between the controller and the service - inconvenient, but much better than multiple services.
source to share
I found a great answer as part of another question. Of course, this / my answer does not participate in bounty. It's just an inspiration that someone explains how things are done these days. So take a look:
- Model classes. They don't get getters / setters for everything. It depends on the model logic. Otherwise, you get a model where you can easily have consistency. Or where there are many non-obvious things. Let's say you have a User.registrationDate field. When you create a new user for an object, you must not forget the field registrationDate field of Hands. So, just put registrationDate in your constructor and remove the setter!
- The repository interface is only inside your model. Suppose you have business logic that depends on existing stored objects. You cannot explain, reference from your domain logic to infrastructure such as JPA, Hibernate, JDBC, etc. Therefore you are requesting this objects from interfaces.
- Business services (optional). They implement some complex logic involving many different organizations, not including security and transaction management. Your question about this. Yes, if you need a request for objects in your domain logic, put the request in the repository and name it from your business service.
- Implementing storage inside an infrastructure package. inventory of repository frontends using JPA or mockito or whatever. They also do not include security or transactions.
- App Services (optional). If there is any complex infrastructure interaction or security check.
- Remote facade interface. Client and server only communicate through the facade's remote interface.
- Remote facade implementation (controller). Converts thick entity objects to thin DTOs (data transfer objects). All transaction demarcation and security here (annotations are often used).
What do you think of this project? Is this applicable for well known spring mvc?
source to share