DDD - which layer DTO should be implemented

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?


Solution 1:

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:

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:

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:

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:

  • Is Layering Worth the Mapping? by Mark Seemann
  • DTO vs Value Object vs POCO: definitions