Replies: 14 comments 6 replies
-
@seoriy very good points. Yes, the presentation layer is using commands and triggering different use cases using those commands and queries which is a partial boundary (using Mediator) between the presentation layer and the application layer.
If you use different entities this would be a different use case i.e another horizontal slice in the app and should define its specific DTOs and use case (this is defined in the book under 'Decoupling use cases') That's at least what I know and got from the book. After all, This is architecture (Not a religion) and architecture is built on decisions. You can definitely clone this template and change it to match your own decision. Even, Uncle bob allowed some drifts from the original design of Clean Architecture, for instance, partial boundaries, and still called it Clean Architecture 💯 |
Beta Was this translation helpful? Give feedback.
-
I disagree with your point. EF Core is not an infrastructure. Infrastructure is DataBase, EF is just a tool. There is no dependency from DB, there is a dependency from EF core. But the same you have a dependency from .NET framework or BCL. I mean it is not reasonable to write an interface for each Framework class. |
Beta Was this translation helpful? Give feedback.
-
In that case it will be ok. As soon as we introduce own abstractions which completely hides chosen framework for implementations it is ok! In that case we will not need that reference to EF Core in Application project, so Dependency Rule will be followed. But the issue is exactly in direct use of DbSet<> inside Application layer and having reference from Application to EF Core and it breaks The Dependency Rule.
No, it is. As well as WebApi:
He hasn't listed ORM directly here, but it definitely should be there. Otherwise, what layer it may be if not an Infrastructure layer (or "Frameworks&Drivers" from the original post)? |
Beta Was this translation helpful? Give feedback.
-
Omg, why the Handler (Application layer) has the context DB in it and why has DbSet TodoLists access? |
Beta Was this translation helpful? Give feedback.
-
@odairto Where is the context DB referenced, would you price the filename and line, please? |
Beta Was this translation helpful? Give feedback.
-
Absolutely. See: This is a direct Db access in app layer. I don't think that clean architecture say this... |
Beta Was this translation helpful? Give feedback.
-
@odairto I think you are in the wrong project, this is CleanArchitecture template, not Northwind project. |
Beta Was this translation helpful? Give feedback.
-
You are right! Sorry! |
Beta Was this translation helpful? Give feedback.
-
Not db context, but it uses DbSet<> from a db contexts directly... |
Beta Was this translation helpful? Give feedback.
-
Personally I agree with the points raised, but then I never understood the difference between Clean Architecture and Onion Architecture to begin with. My choice would be to use concrete repositories with the interfaces defined in the application later and implemented in the infrastructure layer. An example of why that matters can be seen when we think about database optimisation such as vertical partitioning, the virtual keywords, and breaking changes which DO happen (see EF Core 3). I do not believe it is a good idea to mix EF Core with business logic. With that said I saw a talk from the author where he explained his decisions. If I recall this point was addressed as "I would rather embrace EF and have a simpler design. I find it so unlikely I will need flexibility to change db that I dont see an issue". Its not for me, but this is a great project and I dont feel it strays from Clean Architecture, its just not purist and thats ok. |
Beta Was this translation helpful? Give feedback.
-
Quoting the book, application layer (use cases) "We do not expect changes in this layer to affect the entities. We also do not expect this layer to be affected by changes to externalities such as the database, the UI, or any of the common frameworks. The use cases layer is isolated from such concerns." So if i change entity framework or the database to for example a no sql DB, in those case i will have to change all the application layer. so I agree with the original point in this discussion. |
Beta Was this translation helpful? Give feedback.
-
I have checked this project to see how it solves the problem with the EF dependency needed by AspNetCore.Identity. CleanArchitecture/src/WebUI/WebUI.csproj Line 30 in de67f2f For those interested, the best approach to remove this dependency is to implement your custom storage provides. Also you can find some Microsoft documentation here: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity-custom-storage-providers?view=aspnetcore-6.0 |
Beta Was this translation helpful? Give feedback.
-
@sk0va I'm browsing repositories on GitHub for clean architecture and onion architecture, but for some reason, they all seem to apply the same approaches. Is there a repository you can recommend to me where I can see a clean architecture implementation? |
Beta Was this translation helpful? Give feedback.
-
Hey everyone, it's great to see such a lively discussion about implementing Clean Architecture with ASP.NET Core, and I'd like to share my thoughts. Instead of delving into each point individually, I'd like to emphasise that my approach to Clean Architecture is rooted in pragmatism and practicality. When creating a new solution, I always keep the principles of Clean Architecture in mind, while also staying attuned to the real-world context. It's important to strike a balance between adhering strictly to the principles and making reasonable trade-offs that align with the project's requirements. After all, each solution comes with its own unique set of considerations. In some cases, the end result might be a solution that remains agnostic of specific frameworks, while in others, a more direct integration with certain frameworks might make sense. I would encourage each of you to adopt a similar mindset. Reflect on what truly matters for your particular solution and make well-informed implementation decisions. So, while the template doesn't strictly adhere to the principles and does involve some trade-offs, it does offer a straightforward and accessible approach to Clean Architecture with ASP.NET Core in real-world scenarios. It can serve as an excellent starting point, helping you to quickly establish a solid foundation and providing a clear roadmap for customisation based on your project's specific needs. |
Beta Was this translation helpful? Give feedback.
-
It might looks like Clean Architecture, but actually, it doesn't. The original principles are described here - https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
The main principle of The Clean Architecture - The Dependency Rule, is broken in Application project, because it has reference to EF Core. Business layers must not depend on infrastructure layers, but commands use DbSet<> directly, to deal with data. It doesn't comply with The Clean Architecture principles.
Also, domain entities in this solution more looks like a persistent layer entities, rather than domain layer entities.
The purpose of domain layer is to have pure domain abstractions and logic which are independent from application specific. Project may be called "Domain" and has some POCO classes, but if these entities are used mostly as EF Core entities, this is not a domain layer, actually...
It might looks like over-engineering to use separate entities levels for persistence and for domain layers, and all that mappings... Believe me, I'm pretty know, how annoying might be all these mappings! But there are reasons for that. This template solution is just relatively simple and didn't show all possible design issues which might appear in real-life applications... I.e., lets imagine, that we have two entities with many-to-many relation between them - Employee and Company. Yes, I know, this template is for .Net 5, but how about to apply this approach for .NET Core 3.1? In that case, we will need to have some intermediate joint entity to connect Employee with Company and vice versa, right? And queries to DB should use that entities to get related companies by employee and vice versa. But what about domain? do we really need this intermediate entity? The answer is NO, that entity is a persistence layer implementation details only, and it has no sense for domain logic. It useless for a domain logic and business logic. If you would have some other storage type with it's own ORM framework it might not needed in these entities, but it might use some other persistence-only entities. If you have a lot of many-to-many relations domain layer and business logic became harder to read and maintain in that case.
Other problem with Application layer, which uses DbSet<> directly, that it doesn't have unit tests for commands, only integration tests. It's is definitely better to check business logic of a command with unit tests instead of integration tests... Because unit tests are used to check correctness of business logic of a unit, and integration tests are used to checks integration between modules, right?
Presentation layer uses abstractions (commands) from business layer. This is the same kind of design decision issues as for persistence layer.
What if we need to provide additional API, with different entities but using the same logic? In this case we can't just reuse existent command and we will need to choose one of approaches - create new commands and extend existent handlers to support these commands, or introduce additional Response/Request DTO layer and map them to commands. Again, this solution is not showing how to deal with these real-life cases.
By separating entities by layers we are able to maintain layers completely separately. It make code much more flexible and testable, which is the main goal of The Clean Architecture. You may decide to use different UI layers simultaneously (i.e. REST API and message bus interface) for whatever reason, as well as use different persistence layer implementation without need to make changes to business logic.
This solution definitely should have more entity layers to became really an app in The Clean Architecture style.
Conclusion
If this template is called "Clean Architecture", it should follow The Clean Architecture principles. Otherwise, it definitely better to have some other name.
Beta Was this translation helpful? Give feedback.
All reactions