0

The Domain has the Domain Models.

The Infrastructure layer has Commands and Queries, forming CQRS.

Commands return Domain Models, and Queries return DTOs.

In any API, the DTOs are stored in the Application layer, never in the Domain, but if Queries return DTOs, must the DTOs be stored in the Domain? Is it a good idea?

  • 1
    I would dispute the assertion that DTO's live in the "Application Layer," whatever that is. A DTO is simply a Data Transfer Object; you use one wherever you need to package up and transfer data, specifically a record or tuple. See martinfowler.com/eaaCatalog/dataTransferObject.html – Robert Harvey Sep 24 '18 at 17:00
  • There's no reason why you can't use DTOs in commands. If a DTO essentially represents an entity, then why not include it with the other domain models? – Dan Wilson Sep 24 '18 at 17:26
  • There is a similar discussion going on on the PHPDDD repository. Feel free to join: github.com/webdevilopers/php-ddd/issues/14 – webDEVILopers Feb 3 at 10:50
2

Commands return Domain Models, and Queries return DTOs.

Actually, commands should produce side effects and ideally return nothing (which in some cases isn't practical). Queries should have no side effects and return some data. This is all before DTOs even enter the picture.

DTOs are then introduced to essentially "batch up what would be multiple remote calls into a single call" for performance reasons (see Fowler's post). Some relatively complex object structure is flattened in a single object that is serialized for transfer. That means that DTOs are what gets passed to the infrastructure code that implements the commands and the queries at the boundary of the application. Now, to control the dependencies between the layers, it is important to know which layer owns what (not where the objects are stored, but which layer defines and has the ownership of specific types). The same goes for the DTOs. So, whichever layer is the outermost one (while still being logically part of your application), and is calling (and thus is directly dependent) on the libraries/frameworks used to access the remote resource, will be the one that owns the DTOs.

P.S. BTW, note that the idea behind CQRS is to represent the domain in two different ways based on the access patterns, that is, to have two domain models - a Query Model and a Command Model. And these will make use of different sets of DTOs. But in either case, an outer, DTO-owning layer, will receive a request (command or a query) from an inner (higher level) layer, along with some input (maybe a domain object, maybe just some simple parameter set). In case of queries, although they will initially result in DTOs, the code in the inner layer that invoked the query will not get the data as DTOs (because it doesn't "see" the DTO types); instead, in the most general scenario, the outer layer will translate the DTOs into domain objects and return those.

Unless all that's really needed is to show the data on the screen, in which case the outer layer may bypass the inner ones and go straight to the presentation component (which it can do without violating the dependency structure, if it happens within the same "ring" - a layer as seen in clean/onion/hexagonal architecture). In fact, the view itself may bypass the innermost layers as well when issuing the query. And you can get rid of the Query Model entirely if there isn't enough useful behavior to warrant one. What remains may be some component that handles the responsibility of querying, but isn't a full blown model represented by a number of interacting objects. This then allows you to reduce the amount of translating from DTOs to other representations, or to avoid it completely. So you get this picture:

enter image description here

P.P.S. Just to reduce the potential for confusion:
DTOs are, strictly speaking, about remote calls. However, people sometimes use a similar approach when passing data locally, between layers, and call these DTOs (which is arguably muddling the meaning of the term), but this practice should be used sparingly and with good justification, as writing and maintaining the code that translates between representations is a pain. See this article for more info. In the same article, Martin Fowler gives an example of a scenario where this approach is worth considering (focus more on the why, and less on the where):

One case where it is useful to use something like a DTO [in a local context] is when you have a significant mismatch between the model in your presentation layer and the underlying domain model. In this case it makes sense to make presentation specific facade/gateway that maps from the domain model and presents an interface that's convenient for the presentation.

  • The problem is I'm using SQL in the read part (queries). With commands I receive a DTO, I map it to a domain object and I execute the command, but… with queries, I receive a DTO, I map it to a domain object and I return a DTO. If I don't store the DTOs in the domain layer, I can't reference them from the infrastructure layer, where I store the queries. When I program anemic models, I store the DTOs in the application layer. – Jhon Duck Sep 28 '18 at 9:10
1

DTOs, and other messages that cross process boundaries, usually have a different life cycle than the components of the domain model. So what will often happen is that the domain model won't know about the DTO at all, but that there will be some glue code that understands both domain values and the DTO, and transforms from one to the other.

What you will find, in a lot of CQRS designs, is that the domain model really doesn't participate in the query code path at all. Instead, the query code path gets read only access to the values. This may be as simple as read access to the book of record, or it may be read access to a cache of data "projected" from the book of record.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.