DDD - which layer DTO should be implemented

Domain Driven-DesignImplementationLayerDto

Domain Driven-Design Problem Overview


I am learning about DDD so apologies if my question is naive. I think I need to use Local Data Transfer Object in order to display data to the users as a lot of properties are not part of any of Entity / Value Objects.

However, I am not sure where this DTO should be implemented - in a Domain Layer or in an Application Service Layer. The DTO implementation seems part of the Domain, but it means that when I create a collection of DTOs in the Service Layer and pass it to a Presentation Layer, I have to reference Domain Layer in Presentation Layer, which seems wrong.

What is the correct way to implement DTO using DDD principles?

Domain Driven-Design Solutions


Solution 1 - Domain Driven-Design

Define the DTO to the layer where the source of the values comes from.

Relative to OP's question: place the DTO in the Application Service Layer. DTO is an output of that layer, it makes sense if you define it there. Don't put your DTO in the Domain Layer. The Domain Layer does not care about mapping things to serve external layers (the domain does not know there is a world outside of its own).

Presentation Layer (closes to consumers)

  • This could be your API
  • Has Models or Dto definitions of its own with attributes relative to its layer. If this is an API then Models/DTO have attributes for formatting or data type validations
  • This is the "Application Root" (meaning that it must reference both Domain Service layer, Data/Infrastructure Layer to be able to inject services)
  • Maps data between ApplicationService.Dto and Presentation.Dto

Application Service Layer

  • Has Dto definitions of its own to be able to return data without exposing the domain entities.
  • Bridge between Presentation Layer and Domain Layer.
  • Contains Application Services. See answer https://stackoverflow.com/a/3840552/1027250 for detailed definition of Application Services.

Domain Layer

  • Domain entities
  • May contain Interfaces bridging the infrastructure layer, defined in words that can be understood by the business, free from technical terms (IE: IExcelReport, IGoogleSheetReport, IRepository)
  • May contain "Domain Services"

Data / Infrastructure Layer (closest to your database or external services)

  • Database infrastructure (mapping).
  • Excel libraries if you define this layer as infrastructure code.
  • Mail or notification services.
  • PDF output files

Solution 2 - Domain Driven-Design

Such DTOs that are exposed to the outside world become part of a contract. Depending on their form, a good place for them is either the Application Layer or the Presentation Layer.

If the DTOs are only for presentation purposes, then the Presentation Layer is a good choice.

If they are part of an API, be it for input or output, that is an Application Layer concern. The Application Layer is what connects your domain model to the outside world.

As an interesting observation, it follows that the Presentation Layer should access the domain model only through the Application Layer. Otherwise, we lose our single point of access - we'd have multiple layers invoking the domain model. The Application Layer exposes all of our use cases. Whether they are invoked by a call from another service or by the Presentation Layer makes little difference.

Sources

The core of these concepts I learned from The Red Book by Vaughn Vernon. (I would quote from it, but I don't have it handy.) The chapters about the Application Layer and the Presentation Layer are relevant.

Primarily, my conclusions come from being strict with the concepts as presented by Eric Evans and Vaughn Vernon, and prioritizing freedom in the domain model, as this is Domain-Driven Design:

  • The domain model should be easy to change. That means not exposing domain objects externally, as having external dependants would make them hard to change (without breaking things).
  • The Application Layer is the external point of access. It is what defines the use cases on the domain model. That means not operating on the domain model from elsewhere. The Presentation Layer can only go through the Application Layer. Nobody likes having to deal with many different points of access!

Solution 3 - Domain Driven-Design

Yorro is right about where to place DTO but I encourage you to avoid "DTO mindset". This way of thinking collides with DDD way of thinking.

Thinking about "I need a DTO here" is thinking about technical representation (as plalx says); it is a level of abstraction too low. Try a higer level of abtraction and think about your domain, user's tasks and your UI.

Do you need get view data to the user? Bring it to UI through a View Service that return a specific YourViewInfo class.

Do you need to send data to some Service to perform a task? Send it a specific TaskMessageInfo class or a specific Command class.

When you begin to modeling the internals of these classes is when you should start to thinking about its technical representation; then you could reach to the conclusion that could be, i.e., DTO classes for convenience.

Thinking this way helps you to model the system and doesn't trigger questions like

> Where to put or belongs this thing?

Solution 4 - Domain Driven-Design

DTO and Domain are different layers.
So it requires mapping from one to another and usually it is done in what is called Application Services layer.
Take a look at the following articles to go deeper with DTO and layering:

Solution 5 - Domain Driven-Design

Hexagonal (Ports/Adapters) Architecture

What has to be mentioned here is so-called Hexagonal (Ports/Adapters) Architecture [Vernon, the red book p. 125]. It is very convenient to place objects that represent data for the external (outside the domain & the application) comsumers. The architecture is the great addition to Layered Architecture generally implied by DDD.

Here is the example.

Along with ports/adapters for a DBs, email services etc.

We may define a ports/adapters/http/ui/myestore/ShoppingCartResponse.valueobject.ext (assume we use some imaginary programming language EXT) that contains the data your UI application MyEStore will use to show the end user his shopping cart state.

ShoppingCartResponse.valueobject.ext is created by ports/adapters/http/ui/myestore/EStoreHTTP.adapter.ext (for brevity it could be a synonim for a very slim HTTP REST API controller from REST world in our example).

The adapter asks the domain service ShoppingCart.service.ext for aggregates, entities, other value objects. Then it creates the desired ShoppingCartResponse.valueobject.ext from them (by itself or with creators - factories, builders etc.). Then sends the value object as an HTTP response to the consumer.

DTO or Value Object?

Whether ShoppingCartResponse would be a value object or a DTO (.dto.ext) you should decide based on

  • The particular structure of your Ports/Adapters object hierarchy;
  • If it is justified to have another type of object, a DTO, in the system, or it is better to keep only value objects only;
  • A semantic meaning of DTO vs value objects in object hierarchy;
  • The responsibilities differentiation between them: say your value object would do some invariants logic-keeping, whereas DTO could be just a dumb object with no logic.

I would prefer starting with the simplest approach, allowing only for value objects, and add DTOs only as the clear architectural need in them appears.

This approach gives much flexibilty yet it keeps code design clean and simple. Ports/Adapters section accommodates objects that belong together (the adapter, VO or DTO, their creators) and keeps Application Layer clean keeping the space for more relevant application layer objects.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2105030View Question on Stackoverflow
Solution 1 - Domain Driven-DesignYorroView Answer on Stackoverflow
Solution 2 - Domain Driven-DesignTimoView Answer on Stackoverflow
Solution 3 - Domain Driven-DesignjlvaqueroView Answer on Stackoverflow
Solution 4 - Domain Driven-DesignFireAlkazarView Answer on Stackoverflow
Solution 5 - Domain Driven-DesignValentine ShiView Answer on Stackoverflow