dotnet-architecture / eShopOnContainers

Cross-platform .NET sample microservices and container based application that runs on Linux Windows and macOS. Powered by .NET 7, Docker Containers and Azure Kubernetes Services. Supports Visual Studio, VS for Mac and CLI based environments with Docker CLI, dotnet CLI, VS Code or any other code editor. Moved to https://github.com/dotnet/eShop.
https://dot.net/architecture
24.57k stars 10.36k forks source link

[Question] Ordering Queries #592

Closed cmeyertons closed 6 years ago

cmeyertons commented 6 years ago

In the Ordering microservices, why is the OrderingQueries implementation in the application layer? This seems like it be better suited to be in the Infrastructure layer?

And why can't IOrderingQueries be in the domain layer?

I'm relatively new to DDD and read through the Architecting & Developing ebook, and after looking through the code this seemed odd to me.

I would propose performing the following to avoid confusion: Move IOrderingQueries to domain layer Move OrderingQueries to infrastructure layer

I can do the work if approved and necessary

CESARDELATORRE commented 6 years ago

@cmeyertons - Good question. What you say is right for a regular DDD NLayered application. However, the benefits you get from DDD patterns (many of them restrictions related to Aggregates, etc.) are good for the transactional area of your application. But you don't get much benefits for the queries, or I'd say more, for the queries, if using the same aggregates model, entity classes and Repositories than what you use for the transactions, you get many restrictions that are bad and not flexible for the queries (you could not make certain joins you might want for queries, etc.).

Those two topics in reality have different "goals" and if you use the same DDD Domain Model for the queries you will get many limitations in those queries..

Queries are idempotent, no matter how many times you query, data won't change.. ;) - Therefore, in most situations it is better to use a simplified CQRS approach (Command and Query Responsibility Segregation). Therefore, we split the queries logic and code from the transactional area of the application and we apply DDD patterns ONLY for the transactional area. Even the Domain Model with EF Core is used only by the DDD transactional code, not for the queries. Basically, only what's triggered by the Commands is applying DDD patterns and using the DDD Domain Model. But not for the queries.

The database in this simplified CQRS approach is the same database (not two databases, one for transactions and one for queries/reads, that would complicate it significantly), but since we're NOT using DDD patterns for the queries (but plain queries using Dapper) and even the model classes used for the queries is different (different Model/DTO classes) you can have a much better flexibility for querying, i.e. certain joins between tables that in the DDD model would be separated in different aggregates.

That's why the Queries are in the application project, because we're applying DDD only to the transactional area. The queries have certain application logic in the SQL queries, so it is more convenient to put it near the application logic. You could move it to the Infrastructure project, but you wouldn't get a lot of value because of that, but you could do it.

See here my detailed explanation (and the coming pages after that): https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/apply-simplified-microservice-cqrs-ddd-patterns

What would be wrong in this case is to put the IOrderingQueries into the domain layer, since the domain layer is only used for the transactional area in our simplified CQRS. Our queries use a different Reads-Model which is more flexible for queries, as you can check out by researching the code.

Bottom-line, "moving the OrderingQueries to the Infrastructure Layer"? could be, but you won't get much value from that and since we're not applying DDD patterns for the Reads-Queries, that was our design reason.

I hope it clarified the question, which is pretty good since the same project is applying DDD. But it is because of the CQRS approach why it is not like that. Bottom line,

mvelosop commented 6 years ago

Closing this issue. Used to create the (first) post on Simplified CQRS and DDD in the Knowledge Base

LREMe commented 2 years ago

Hi @cmeyertons , @CESARDELATORRE This is the question / answer that I was looking. Many companies/developers are crazy about DDD and other patterns. I was looking at the samples and I was wondering: why you make that difference?. Also, it observed that you are creating a "mini" DDD just for the queries (so you have 2 DDD's).

I have to add and extra comment, maybe the best solution is to put the queries on stored procedures: out from the code. When you have an application with really high use, a problem that may arise is that the queries will degrade and you will be looking at historical data migration strategies, or requiring more computing power (and not always you are going to be allowed to solve it on that way). You need to analyze your queries, see if you need keys, and if you database is correctly maintained, recompile keys or add some. RDBMS allows you to optimize plans and gives you an extra.

I'm returning to be a full time developer after like 10 years, and looking at the practices, I'm seeing that the applications may have a lot of performance issues because the extra layers. Respecting patters is a good way to reassure maintenance, but, on daily operations the users will hate you if your application is not performing well (I had to correct performance issues with an application on the last month that was respecting patterns, but not using store procedures in any way: after changing some key parts to procedures, creating keys and recompiling them, the application returned to work correctly: none of the team were able to see the problem because they use only EF - not like in the old days :D - ).

Thanks