Should services always return DTOs or can they also return domain models?

I (re) develop a large-scale application, we use a multi-level architecture based on DDD.

We have MVC with a data level (implementation of repositories), a domain level (definition of a domain model and interfaces — repositories, services, unit of work), a level of service (implementation of services). Until now, we use domain models (mainly entities) across all layers, and we use DTO only as view models (in the controller, the domain model (s) are returned to the service, and the controller creates a view model that is passed to the view).

I have read countless articles about using, not using, comparing and passing DTO. I understand that there is no definitive answer, but I'm not sure if it is normal or not, returning domain models from services to controllers. If I return the domain model, it still never goes to the view, since the controller always creates the view model based on the view - in this case it seems legal. On the other hand, this does not seem to be correct when the domain model leaves the business layer (service level). Sometimes a service needs to return a data object that was not defined in the domain, and we need to either add a new object to the domain that is not displayed, or create a POCO object (this is ugly, as some services return domain models, some effectively return DTOs).

Question: if we strictly use viewing models, is it normal to return domain models to the controller, or should we always use DTO to communicate with the service layer? If so, is it okay to configure domain models based on what services are needed? (Honestly, I don’t think so, because services should consume what the domain has.) If we must strictly adhere to the DTO, should they be defined at the service level? (I think so.) It is sometimes clear that we must use DTO (for example, when the service runs a lot of business logic and creates new objects), sometimes it is clear that we should use only domain models (for example, when the membership service returns anemic User ( s) - it seems it makes no sense to create a DTO, which matches the domain model), but I prefer consistency and good practice.

Article Domain against DTO and ViewModel - how and when to use them? (as well as some other articles) is very similar to my problem, but it does not answer this question (s). Article Should I use DTO in the repository template with EF? also similar, but it is not related to DDD.

Disclaimer: I do not intend to use any design pattern just because it exists and is fantastic, on the other hand, I would like to use good design patterns and practices also because it helps to develop the application as a whole, helps with sharing problems, even if the use of a specific template is not "necessary", at least for now.

Thanks as always.

+106
architecture asp.net-mvc entity-framework domain-driven-design
Feb 04 '14 at 14:19
source share
7 answers

it doesn’t feel good when the domain model leaves the business layer (service level)

Makes you feel like you're just pulling out your guts? According to Martin Fowler: the boundery application determines the level of service, it encapsulates the domain. In other words, it protects the domain.

Sometimes a service needs to return a data object that was not defined in the domain

Can you give an example of this data object?

If we must adhere strictly to the DTO, should they be defined at the service level?

Yes, because the answer is part of your level of service. If it is defined “somewhere else,” then the service level should refer to “somewhere else,” adding a new layer to your lasagna.

Is it normal to return domain models to the controller, or should we always use DTO to communicate with the service level?

A DTO is a response / request object, it makes sense if you use it for communication. If you use domain models in your presentation layer (MVC-Controllers / View, WebForms, ConsoleApp), then the presentation level is closely related to your domain, any changes in the domain require changes to your controllers.

it seems that it makes no sense to create a DTO, which matches the domain model)

This is one of the drawbacks of DTO for new eyes. Right now you are thinking of duplicating code , but as your project expands, it will make more sense, especially in a team environment where different teams are assigned to different layers.

DTO may add extra complexity to your application, but also your layers. DTO is an expensive feature of your system; they are not free.

Why use DTO

This article presents both the advantages and disadvantages of using DTO, http://guntherpopp.blogspot.com/2010/09/to-dto-or-not-to-dto.html

The summary is as follows:

When to use

  • For large projects.
  • Project lifetime is 10 years and older.
  • Strategic, critical application.
  • Large teams (over 5)
  • Developers are distributed geographically.
  • The domain and presentation are different.
  • Reducing overhead sharing (DTO original goal)

If not use

  • Small and medium sized project (maximum 5 members)
  • The service life of the project is 2 years.
  • There is no separate command for GUI, backend, etc.

Arguments Against DTO

Arguments with DTO

  • Without DTO, presentation and domain are closely related. (This is normal for small projects.)
  • API Interface / Stability
  • It can provide optimization for the presentation layer by returning a DTO containing only those attributes that are absolutely necessary. Using linq-projection , you don't need to pull the whole object.
  • To reduce development costs, use code generation tools.
+110
Feb 05 '14 at 6:00
source share

In my experience, you should do what is practical. "The best design is the simplest design that works" - Einstein. With this mind ...

if we strictly use viewing models, is it normal to return domain models to the controller, or should we always use DTO to communicate with the service layer?

Absolutely normal! If you have domain objects, DTO and viewing models, as well as database tables, all fields in the application are repeated in 4 places. I worked on large projects in which domain objects and view models worked fine. The only temptation in this case is the distribution of the application and the level of service on another server, in which case DTOs must be sent over the network for serialization reasons.

If so, is it okay to configure domain models based on what services are needed? (Honestly, I don’t think so, since services should consume what the domain has).

Usually I agree and say no, because the domain model is usually a reflection of the business logic and is usually not formed by the consumer of this logic.

If we must adhere strictly to the DTO, should they be defined at the service level? (I think so.)

If you decide to use them, I agree and I will say that the level of service is an ideal place, since it returns DTO at the end of the day.

Good luck

+8
Jul 05 '14 at 10:10
source share

It seems that your application is quite large and complex since you decided to use the DDD approach. Do not return your poco entities or so-called domain entities and value objects in your service layer. If you want to do this, then remove the service layer, because you no longer need it! View Model or Data Transfer objects must be in the Service layer because they must map to members of the domain model and vice versa. So why do you need a DTO? In complex applications with a large number of scenarios, you must separate the interests of the domain and presentation, the domain model can be divided into several DTOs, and several domain models can be combined into DTOs. So it’s better to create your own DTO in a tiered architecture, even if it is the same as your model.

Should we always use DTO to communicate with the level of service? Yes, you should return the DTO according to the level of service, since you communicate with your repository at the service level with members of the domain model, map them to the DTO and return them to the MVC and vice versa.

Is it possible to adjust domain models depending on what services are needed? The service simply interacts with the methods of the repository and domain and domain services, you should decide the business in your domain based on your needs, and not the task of the service to tell the domain what you need.

If we must adhere strictly to the DTO, should they be defined at the service level? Yes, try using DTO or ViewModel later only because they must be mapped to domain members at the service level, and it is not recommended to put DTOs in the controllers of your application (try using the service request response template), hooray!

+7
Feb 04 '14 at 18:06
source share

Until now, we use domain models (basically entities) at all levels, and we use DTO only as viewing models (in the controller, the domain model model (s) is returned to the service, and the controller creates a view model that is passed to the view).

Since the domain model provides the terminology ( ubiquitous language ) for your entire application, it is better to use the domain model.

The only reason for using ViewModels / DTO is the implementation of the MVC pattern in your application to separate View (at any level of presentation) and Model (domain model). In this case, your presentation and domain model are loosely coupled.

Sometimes a service needs to return a data object that was not defined in the domain, and then we either need to add a new object to the domain that is not displayed, or create a POCO object (this is ugly, as some services return the model domain, some effectively return DTO) .

I assume that you are talking about Application / Business / Domain Logic services.

I suggest you return the domain objects when you can. If you need to return additional information, it is permissible to return a DTO that contains several domain objects.

Sometimes people who use the third part frameworks that generate proxies over domain entities find it difficult to expose domain objects from their services, but this is only a matter of misuse.

Question: if we strictly use viewing models, is it normal to return domain models to the controller, or should we always use DTO to communicate with the service layer?

I would say that it is enough to return domain objects in 99.9% of cases.

To simplify the creation of DTOs and display domain objects in them, you can use AutoMapper .

+3
Feb 04 '14 at 18:14
source share

I would suggest analyzing these two questions:

  1. Are your top layers (e.g. view & view models / controller) consuming data in a different way than the domain layer expands? If a lot of mapping is done, or even logic, I suggest revising your design: it should probably be closer to how the data is actually used.

  2. How likely is it that you deeply change your upper layers? (e.g. ASP.NET replacement for WPF). If this is very different and your architecture is not very complex, you might be better off exposing as many domain objects as you can.

I am afraid that this is a fairly broad topic, and it really depends on the complexity of your system and its requirements.

+1
04 Feb '14 at 16:13
source share

I'm late for this party, but this is such a common and important question that I had to answer.

By "services" do you mean the "application layer" described by Evan in the blue book ? I assume you are doing, in which case the answer is that they should not return a DTO. I suggest reading Chapter 4 in a blue book called Domain Isolation.

In this chapter, Evans says the following about layers:

Break a complex program into layers. Design a design within each layer, which is cohesive and depends only on the layers below.

There is a good reason for this. If you use the partial order concept as a measure of software complexity, then having a level depending on the level above increases complexity, which reduces usability.

Applying this to your question, DTOs are indeed an adapter that relates to the user interface / presentation level. Remember that remote / interprocess communication is exactly the purpose of the DTO (it is worth noting that in this post Fowler also argues against the DTO, which is part of the service level, although he does not necessarily speak DDD).

If your application level depends on these DTOs, it depends on the level above you, and your complexity increases. I can guarantee that this will increase the complexity of maintaining your software.

For example, what if your system interacts with several other systems or types of clients, each of which requires its own DTO? How do you know which DTO method your application service should return? How would you solve this problem if your language does not allow you to overload a method (in this case, a service method) based on the return type? And even if you come up with a way, why break your application layer to support the presentation layer problem?

In practical terms, this is a step along the path that will end with spaghetti architecture. I have seen this kind of devolution and its results from my own experience.

Where I work now, services of our level of applications return domain objects. We do not consider this a problem, since the level of the interface (i.e., the User Interface / View) depends on the level of the domain that is under it. In addition, this dependency boils down to a link-only type of dependency because:

a) The interface layer can only access these domain objects as read-only return values ​​obtained by accessing the application layer

b) service methods at the application level accept only “raw” input data (data values) or object parameters (to reduce the number of parameters where necessary) defined at that level as input. In particular, application services never accept domain objects as input.

The interface layer uses the mapping methods defined in the interface layer itself to map from Domain objects to the DTO. Again, this allows the DTO to focus on being adapters that are controlled by the interface layer.

+1
Dec 19 '16 at 20:53 on
source share

In my experience, if you are not using a UO UI template (for example, nude objects), exposing domain objects in the user interface is a bad idea. This is because as the application grows, the user interface needs change and make your objects take these changes into account. As a result, you get 2 wizards: UI and DOMAIN, which is a very painful experience. Believe me, you do not want to be there. The user interface model has a user communication function, the DOMAIN model for conducting business rules, and the persistence model has effective data storage. All of them affect the various needs of the application. I am in the middle of writing a blog post about this, I will add it when it is done.

+1
Dec 05 '18 at 18:28
source share



All Articles