0
votes

I try to implement DDD service with using of CQRS approach. I'm not using event sourcing. So I have 3 layers: Application, Infrastructure, and Domain. Many peoples said that you can bypass domain for queries, and it is okay. For example, imagine it is necessary for me because of performance issues.

Following persistence ignorance, I have repository implementation in Infrastructure. As I see in all implementations of DDD and books, Infrastructure should not be dependent on the Application layer.

So what I need to return from the repository?? If DTO(Read models, View models, it actually doesn't matter) is an Application concern. Placing them on the Infrastructure layer makes a circular dependency from Application to Infrastructure and vice versa. But implementing query logic (if I using Orm which queries by writing raw SQL) is a bad approach because for that purpose we have created the repository in Infrastructure (That was the way of https://github.com/dotnet-architecture/eShopOnContainers).

Another approach is load aggregates from the repository and then convert them to DTO, but it is impossible due to my fictional issues. So how to deal with that in the right way? (That was the way of https://github.com/JasonGT/NorthwindTraders/)

3

3 Answers

0
votes

If you want to follow Clean Architecture by Robert C. Martin, you should separate stable business rules (higher-level abstractions) from volatile technical details (lower-level details), defining clear boundaries. Your source code dependencies should point only inward, toward higher-level policies. To achieve this, use the Dependency Inversion principle. Define Interfaces for repositories in layer where you need them. Then implement those repositories in Infrastructure layer.

That means Application layer should not depend on Infrastructure layer. But Infrastructure layer can depend on Application layer (Infrastructure can use Application).

0
votes

An idealized read model looks a lot like a cache -- you get a query, you use the query to compute a cache key, you return the bytes that are stored using that cache key.

What happens on a cache miss? Then you have to go look up the data, and compute what the bytes returned should be.

So what you are trying to achieve is fetching the state you need from your durable store, and then converting that state into the serialized representation that the caller will understand, with no unnecessary fuss.

For example, imagine a web API, where the client passes you a target uri and expects an application/json response. Your stateful data store is some RDBMS, so you use your off the shelf sql client to execute a query, which produces a ResultSet. You would then use something like a DOM builder to build a tree, iterating over the rows in the result set and copying the columns of data into the tree. When the tree is done, you would use your json library to extra a UTF-8 representation of the tree. Tada, you've got a representation of the response that you can stick in the cache and return to the client.

If you are more comfortable with O/RM, then you might define an in memory object representation, and let the O/RM worry about creating an in memory representation of the result, which you then pass to the JSON deserialization library.

The point here is that this translation component needs to understand how to interpret the value that has been retrieved from the durable store, and how to express that value in a representation that will be understood by the client -- but you don't need entities. You are "just" taking messages and turning them into other messages.

Depending on which parts of the translation are stable and which need to be substitutable, you might have any of a number of useful designs here. But the implementation of your translation doesn't need to have any dependencies on the implementation details of your write model.

0
votes

As I see in all implementations of DDD and books, Infrastructure should not be dependent on the Application layer.

That's not truth at all. Infraestructure depends on Application Layer. Look at Figure 4.3 (page 124) of Vaughn Vernon's red book IDDD.

For example, cross-cutting services (authentication and authorization, transactional, etc) are defined at application layer, and the implementation is at infraestructure.

So what I need to return from the repository?? If DTO(Read models, View models, it actually doesn't matter) is an Application concern. Placing them on the Infrastructure layer makes a circular dependency from Application to Infrastructure and vice versa. But implementing query logic (if I using Orm which queries by writing raw SQL) is a bad approach because for that purpose we have created the repository in Infrastructure

If you are using CQRS, you have a different model for Querys. Repositories are part of Command model. In the Q model you define the query you need in the application layer, returning objects needed by the client (e.g. a view). The implementation of the query is in the infraestructure layer, using SQL directly.