Get the source code for this video for FREE → the-dotnet-weekly.ck.page/clean-onion Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
I used to implement my feature handlers in the Application layer even though they use ORM (DbContext). But now I see you bring them into Infrasructure (Persistence) layer. Is this by the rule or it is just your approach?
It have to be in application layer because you often want more than just use a database. If the use Case need more information or requires more than one infrastructure, you are forced to gather this in application.
Great video, also thanks for not focusing on theory only and including the example projects from the scratch. Some things are best learned with an example
Good video. 👍A couple of thoughts: * Service interfaces is useful for unit tests when services depends on other services. * Recommend also setting the respository impl classes (and others) as internal so they can't be accessed by other layers. Only keep a public class with extension methods to IServiceCollection to add them into the DI flow.
I see a lot of comments about the Query handlers been in the infrastructure layer. Your reason being: "For a query usually don't care how it's implemented, I only care about the result I get back." This makes sense to me. Will definitely switch to doing this because keeping all the query concerns in the infrastructure is to me a much better separation of concerns. Thank you for sharing
This is how I am currently doing it. It works, but having infra stuff like the ORM in the app layer really bothers me. That is why it made sense when you mentioned having the Query Handler in the infra layer. However, after thinking about this for a bit, I realised this is a separation concern for me. I will add an extra layer, the Query Layer, dependent on the infra and domain layers; this is where the query handler will be. The presentation layer will then depend on the query layer and app layer. Queries go to the Query layer, and Commands go to the Application layer. This approach aligns with the CQRS pattern and would align with my architectural concerns. I have even considered renaming the app layer to the command layer. I have been trying to shoehorn the CQRS pattern into clean architecture, so the results have bothered me. But this would clear that up for me. I'm rambling here a bit; it's easier for me to formulate an idea when I have to define it, and it's also good to have feedback on it when you put it out there.
Nice video! I used to see it as if onion architecture were part of clean architecture! At the end, they shared some of their philosophy. Thanks, Milan!
The front-end command needs to create an order and create a payment at the same time, and this operation should be logically processed at the order application layer? Or is it processing logic at the endpoint?
I have a small question. Why didn't u put the QueryHandler in the Application layer and then inject a repository (which is located in the Domain layer) into that QueryHandler? That way, you can get rid of references to DbContext (external concern).
Repositories should return domain entities. If I use that in a query handler - it's not optimal performance. If I start returning DTOs from the repository, it starts getting too many concerns.
I was asking myself the same exact question. Imo, the not using the repository in the query handler for performance reasons argument doesn't hold water. As a matter of fact, the approach presented in this video leaks application layer specific logic, i.e. the business logic, in the external layer. The Article Service is practically mapping user input to domain entities & passing them to the Article Repository. The Query Handler should be no different; it should map domain entities returned by the repository to dtos which are then consumed by the external layers.
These are not necessarily like for like comparisons... For eg, Onion Architecture doesn't appear to use MediatR while Clean Architecture does... In which case Clean Architecture has Application project with a library dependency on MediatR which does not make it technology agnostic... This imo should be in Infrastructure... Pls suggest
Application layer acts somewhat as the request orchestrator ( calling different services using interfaces and also calling domain services/ invariants in the process). Persistence purely deals with database stuff .so shouldn't handlers related to query also be in application layer and use the repository interface ( for getting an article in this example)? This way also provides higher cohesion IMO
@@MilanJovanovicTechPreventing references to any external concerns in application layer ( just like the thing you did in creating an article command handler)
Thanks Milan for this explanation. When building an enterprise application with lots of entities, would it be practical to use the Clean Architecture, it appears to me that you would need a lot of query handlers and commands, which is a lot of code compared to using services? Then secondly, is there a need to use a Repository pattern if using EF Core, is this not just an extra layer?
11:44 I don't agree with putting the handler down in infrastructure. In that case I would rather do something like an ArticleQueryService/ArticleReadRepository that holds the queries. But regardless I find both of these architectures very bloated and see little use case of actually using them unless you are building a big monolith, which in todays world with all cloud providers you rarely do.
Hey Milan, I've just discovered your videos and really enjoying them. I was just wondering if your Visual Studio theme is something available/easy for us to use? The syntax colors appear easier on the eyes than the default theme. Thanks!
Yes, I understand it is a messaging library. But, if I wanted to use these use cases in another application, isolating it in a project, wouldn't it be better not to create this dependency, since in the other application I might not use MediatR?
@@lindermannla If you are really concerned, you could only reference Mediatr.Contracts in the application layer and then the full mediatr in the presentation (application root) layer.
Great video! I have the same question. Why is Automapper considered external concern but not MediatR? Using MediatR for convience is a acceptable answer :)
@@davidaltran8526 Isn't mapping usually done in the Web project/layer? Map requests to commands and entities to responses ??? I guess I could see the entity to response mapping being done in the application layer. But not where I do it.
I can't see differences, just synonyms, because all the examples I see of both have things implemented in one and not in the other, but that don't belong to the model, this takes the focus away from the comparison, it would be interesting to leave preferences aside and focus on implement the same functionalities in both, without a mediator, without a mapper, and all these things that can be implemented in both, but are not necessary to compare, especially if there is only an example of the code in Onion or Clean
What about placing Automapper in Application layer? Doesn't that bind it with business logic? If at a later stage, another mapper or custom mapper is needed, it would require many changes to decouple old mapper and then implement new... Do you think it's better to have mapper in Infra ?
@@MilanJovanovicTech agree... They are slim but can't be ruled out... I had to recently replace Automapper with a more optimized mapper as my application was very large and Automapper was taking toll on memory... That's when I realized I needed Clean Architecture as Automapper was tightly engrained with every single project... Having it in Infra helps me as I can swap out very easily
hi Milan, thanks for these details. are the hexagonal architecture and onion architecture the same ? what about ports and adapters architecture ? thanks
I would say hexagonal is a bit "different" from an implementation perspective, more moving parts. But the result is pretty much the same, in terms of direction of dependencies.
IMO both these architectures become a mess within a couple of days into development. We ditched them and switched to vertical slice architecture. It has been over an year now and we now maintain huge projects with ease. It would be great if you could compare it as well. Kudos to your work.
Within a couple of days? I've maintained CA/Onion systems for years, and they didn't become a mess. Maybe it's not the architecture, but the engineers...
interesting. This is the first time I've seen anyone put the query handlers in the infrastructure (persistence) project. I've mostly seen the query handlers in the Application project which is also where the command handlers are. Do you see an advantage to putting them there?
Avoiding a reference to any persistence mechanism in the Application layer. And continuing down that train of thought, it makes sense. For a query I usually don't care how it's implemented, I only care about the result I get back. So I can move the details of that to Infrastructure. For command handlers, I definitely care about the implementation because it has business logic, so I want it in the Application layer. This is an idea I got from Jeffrey Palermo's Onion Architecture repo, and I just adapted it to MediatR.
@@MilanJovanovicTech So your repositories implementation only have the queries needed for the command handlers? And your query handlers use EF dbcontext directly I assume? Frankly, though, I consider Queries a use case so prefer them in the UseCase (application) project. So many ways to skin the cat I guess.
This goes very well hand in hand with the asymmetric approach DDD/CQRS follows. The write side of the application tends to be more strict and specific than the read side that can just fetch the data however it wants. Which would make the Domain project (Entites + Repositories) less significant for the read side.
@@kostasgkoutis8534Yes, I like the suggestion that there is a projection that matches each "view" in the UI so the query is nothing more than select * from CustomerSummaryView (or whatever) But, I've never got to this point.
Thank you for this wonderful video. I have been using both architecture without having a clear understanding of the disticntion between the two architecture, and this video has cleared all grey areas. I noticed the Persistent project references the Domain project, is this allowed in clean architecture? My understanding is that only the application layer should reference the domain layer, but in your exmaple I see the "Article" object spanning across all layers up to the persistent/infrastructure layer.
Uncle Bob didn't tell us "how to implement Clean Architecture". so for me "Architecture" is just Onion. The concept of Clean Architecture could simply be called "Clean Code Design"
@@MilanJovanovicTech It is simple, Clean Architecture does not strictly specify how to organize the outer layers. Onion Architecture, on the other hand, is more prescriptive about organizing the external layers, requiring them to contain specific infrastructure details, such as database access and UI.
Nice video and explanation but there isn’t much difference based on this tutorial. Just naming and package, for the onion architecture you used services and EFcore while for the clean architecture you used command and mediatr.
Thank you for the explanation, but I still don't see the difference. You've used MediatR in the Onion architecture, but not in the Clean architecture. Does using MediatR in the Onion architecture mean we've migrated to the Clean architecture?
Apart from grouping features with folders what different thing does the clean architecture actually brings? It keep confusing me. Everyone implements it differently. I love onion. Simple and straight forward 😊😊
Bro do you have any plans on making a videos series on an entire application from start to finish? frontend backend, db, containers, the whole 9 yards.
Hey Milan, i have a question about Onion Architecture, you created a Article entity in Domain project, and you used this entity in Persistence project with ArticleRepository, this is not a problem because you are using a Code First DB but what if i use database first? My Article will be created with properties based on my database columns (SQLServer, MySQL, etc). This is a problem, because my Domain will be depends of Persistence
You can either: - Use the scaffolded model, if possible, from the Domain (probably not possible) - Map from domain to "persistence" model - Add a DbContext that uses domain model, and can persist to DB?
Does anyone knows why the clean architecture doesn't represent the repository (repo interfaces) in its diagram + I didn't understand the point of making a requestQuery class in the usecases then injecting the dbContext and implementing it in the infrastructure rather than just declaring GetArtictleByIdQuery method in the repo interface then implementing it in the infrastructure and using just like the other requests and request handlers in the usescases
I personally would argue that mediator is part of a framework. That is why I am not using it, because every usecase class will depend on that library in the end. And use cases should describe pure business logic. I get why it is very convenient, but are you not a bit hesitant regarding the hard dependency?
5:59 - IArticleRepository interface references your Api. Have a look at the top using statement. It's against either onion and clean architecture rules.
No, that's just the namespace of the Article (which should be Domain.Entities though) 5:39 But the project references are correct. You can grab the source code and check (pinned comment).
I think it is confusing to have a use-case (GetArticleById) in the application layer, where you only define the query and the response, and the developer is expected to know to implement the handler in the persistence layer. Wouldn't it be better to define a IArticleReadRepository interface, implement it in the persistence layer, and then implement the GetArticleByIdQueryHandler in the application layer, injecting the IArticleReadRepository into it?
Having an IArticleReadRepository defeats the purpose of GetArticleByIdQueryHandler. The GetArticleByIdQueryHandler becomes a wrapper calling an interface method. What's the value in that?
@@MilanJovanovicTech Thank you very much for the link! I agree, it does seem pointless to create all this unnecessary abstraction with read services, if all we are doing is running a simple query.
Great video, Milan. Very practical info, rather to see your video to quickly be a up to speed, than reading a 500 pages Clean arquitecture book :P Thanks !
Im little bit confused here. Onion focus on services and clean focus on use cases. But service contains the use cases, isn't it? Then What is the difference actually, Can anyone explain it.
Onion, Clean, or whatever are just branding of the same thing. The most important part of this is the concept, not the implementation details or the name. Implementation might diverge and adapt to your needs.
I think Clean architecture is more complicated than described in the video. Some key points - bounded context, domain objects are missed. Domain objects are completely different in onion ad clean, in clean you can`t simply take domain object and save it.
I wanna add, that most design patterns (including architecture) are just a theory of how to do certain stuff. But its not a strict rule, so the Clean Architecture can be implemented with different outcomes.
Cool idea to explain differences between those two approaches👌The layer is thin.. 😁 On a personal note I'm so glad CleanArchitecture has become more popular. I'll always remember the face of the people I tried to explain/sell "Onion" architecture benefits. Lost half of them right at the beginning 🧅🤥
In clean architecure the repository belongs to the application layer not the domain. The use cases should be exposed as inbound ports of the app layer and they should not be commands, they could however be implemented underneath as commands, but that's a technical detail that the caller does not need to know. A use case should also be named as Use Case at the end, for example AddOrderUseCase to make clear we are talking about use cases and not services or bananas. All the external dependencies of the application layer should be defined in a separate project called application.ports.outbound which is the one that the external layers will implement.
UseCase = Command/Query, same thing. "All the external dependencies of the application layer should be defined in a separate project called application.ports.outbound which is the one that the external layers will implement" - Too much work for not so much benefit. We'll end up with dozens of projects if we go down this route.
a VERY simple project. Why not show how a real world project is implemented... That will give a much better insigts in the real problems that you never need to handle in such simple examples..
@@MilanJovanovicTech I dont think so. Obviously you vcannot write that system from scratch but you can show diagrams of it and show exampkes of real code. these kind of simplified examples doesnt really help. it just fools people.
Is it the architecture that's trash or the project organization? Code to interface not implementation is a pretty well-established OOP principle. That said, why is it "trash"? Objective evidence, please.
Anyone saying this has no Idea imho! 😂 sorry, but this architectures keep the most basic and ever important keypoints. You will always have to deal with dependencies and layers. Have Met alot of people saying the same, watching their "architectures" and know whats their problem.. they are mostly beginners, although few of them programming for tons of years.
Get the source code for this video for FREE → the-dotnet-weekly.ck.page/clean-onion
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
why not just in github ?
My architecture is like an Onion - it has many layers, and each time you peel one to expose a deeper layer it makes you want to cry.
😂
😂
😂
Ah, we really needed a video on this topic, a comparison between these seemingly similar architectures. Thanks!
Glad you liked this one :)
I used to implement my feature handlers in the Application layer even though they use ORM (DbContext). But now I see you bring them into Infrasructure (Persistence) layer. Is this by the rule or it is just your approach?
Just an idea I got from Jeffrey Palermo's original Onion Architecture repository.
It have to be in application layer because you often want more than just use a database. If the use Case need more information or requires more than one infrastructure, you are forced to gather this in application.
Great video, also thanks for not focusing on theory only and including the example projects from the scratch. Some things are best learned with an example
I think this aligns nicely with my way of teaching. Some theory, but more focus on practice and practical implementations
Good video. 👍A couple of thoughts:
* Service interfaces is useful for unit tests when services depends on other services.
* Recommend also setting the respository impl classes (and others) as internal so they can't be accessed by other layers. Only keep a public class with extension methods to IServiceCollection to add them into the DI flow.
Great suggestions 👌
One question here, in case of using onion architecture, service interfaces would be placed in application layer or domain layer?@@MilanJovanovicTech
@@riseofaskariAll the interfaces that are used in the infrastructure layer are stored in the domain layer.
Thank you Mr. Jovanovic. You are first one (not FirstOrDefaul :D ) who explained it so cleaner. And with demo. Good job!
Glad it was helpful!
I see a lot of comments about the Query handlers been in the infrastructure layer. Your reason being: "For a query usually don't care how it's implemented, I only care about the result I get back." This makes sense to me. Will definitely switch to doing this because keeping all the query concerns in the infrastructure is to me a much better separation of concerns. Thank you for sharing
Another thing I do is leave them in Application layer, and simply use EF/SQL/Whateveriwant. Not pure CA, but same result with less indirection.
This is how I am currently doing it. It works, but having infra stuff like the ORM in the app layer really bothers me. That is why it made sense when you mentioned having the Query Handler in the infra layer.
However, after thinking about this for a bit, I realised this is a separation concern for me.
I will add an extra layer, the Query Layer, dependent on the infra and domain layers; this is where the query handler will be. The presentation layer will then depend on the query layer and app layer. Queries go to the Query layer, and Commands go to the Application layer. This approach aligns with the CQRS pattern and would align with my architectural concerns. I have even considered renaming the app layer to the command layer.
I have been trying to shoehorn the CQRS pattern into clean architecture, so the results have bothered me. But this would clear that up for me.
I'm rambling here a bit; it's easier for me to formulate an idea when I have to define it, and it's also good to have feedback on it when you put it out there.
Nice video! I used to see it as if onion architecture were part of clean architecture! At the end, they shared some of their philosophy. Thanks, Milan!
Yeah, they are interchangeable
The front-end command needs to create an order and create a payment at the same time, and this operation should be logically processed at the order application layer? Or is it processing logic at the endpoint?
You can process them both on the backend, as one transaction.
I have a small question. Why didn't u put the QueryHandler in the Application layer and then inject a repository (which is located in the Domain layer) into that QueryHandler? That way, you can get rid of references to DbContext (external concern).
Repositories should return domain entities. If I use that in a query handler - it's not optimal performance. If I start returning DTOs from the repository, it starts getting too many concerns.
I was asking myself the same exact question. Imo, the not using the repository in the query handler for performance reasons argument doesn't hold water. As a matter of fact, the approach presented in this video leaks application layer specific logic, i.e. the business logic, in the external layer. The Article Service is practically mapping user input to domain entities & passing them to the Article Repository. The Query Handler should be no different; it should map domain entities returned by the repository to dtos which are then consumed by the external layers.
Thanks Milan! Great video! It would be interesting to see Hexagonal architecture comparison as well :)
Great suggestion!
Its the same as the clean architecture. Just another visualization in my opinion.
These are not necessarily like for like comparisons... For eg, Onion Architecture doesn't appear to use MediatR while Clean Architecture does... In which case Clean Architecture has Application project with a library dependency on MediatR which does not make it technology agnostic... This imo should be in Infrastructure... Pls suggest
Not necessarily, architecturally they are pretty identical. Disregard the implementation details.
I dont know why that i'm not find you before. You have videos for all of my doubts. Thankssss!!
Happy to help 😁 Hope you enjoy the other videos :)
I prefer 📂 s named UseCaseViaService and UseCases then individual folders for each use. More for future organizational planning.
Expand on this with an example? I'm curious what you mean
Great video, my friend. Now I have a clear concept of those two architectures. Thanks a lot!
Don't you think they are the same?
Application layer acts somewhat as the request orchestrator ( calling different services using interfaces and also calling domain services/ invariants in the process). Persistence purely deals with database stuff .so shouldn't handlers related to query also be in application layer and use the repository interface ( for getting an article in this example)? This way also provides higher cohesion IMO
What would be the value of that indirection via the repository?
@@MilanJovanovicTechPreventing references to any external concerns in application layer ( just like the thing you did in creating an article command handler)
Thanks Milan for this explanation. When building an enterprise application with lots of entities, would it be practical to use the Clean Architecture, it appears to me that you would need a lot of query handlers and commands, which is a lot of code compared to using services? Then secondly, is there a need to use a Repository pattern if using EF Core, is this not just an extra layer?
You're free to use EF directly. It's more or less the same amount of code (+-10%) but it's in different places.
11:44 I don't agree with putting the handler down in infrastructure. In that case I would rather do something like an ArticleQueryService/ArticleReadRepository that holds the queries.
But regardless I find both of these architectures very bloated and see little use case of actually using them unless you are building a big monolith, which in todays world with all cloud providers you rarely do.
What is a "big monolith"?
Let me congratulate you because of the videos you do. You are very clear with your explanations!
Thank you very much!
Hey Milan, I've just discovered your videos and really enjoying them. I was just wondering if your Visual Studio theme is something available/easy for us to use? The syntax colors appear easier on the eyes than the default theme. Thanks!
It's VS dark theme + ReSharper syntax highlighting
Milan one question, in your Clean Architecture example, in the Core/Application "layer", isn't it a conceptual flaw to create a dependency on MediatR?
Why? It's just an in-memory messaging library
Yes, I understand it is a messaging library. But, if I wanted to use these use cases in another application, isolating it in a project, wouldn't it be better not to create this dependency, since in the other application I might not use MediatR?
@@lindermannla If you are really concerned, you could only reference Mediatr.Contracts in the application layer and then the full mediatr in the presentation (application root) layer.
Great video! I have the same question. Why is Automapper considered external concern but not MediatR? Using MediatR for convience is a acceptable answer :)
@@davidaltran8526 Isn't mapping usually done in the Web project/layer? Map requests to commands and entities to responses ???
I guess I could see the entity to response mapping being done in the application layer. But not where I do it.
I can't see differences, just synonyms, because all the examples I see of both have things implemented in one and not in the other, but that don't belong to the model, this takes the focus away from the comparison, it would be interesting to leave preferences aside and focus on implement the same functionalities in both, without a mediator, without a mapper, and all these things that can be implemented in both, but are not necessary to compare, especially if there is only an example of the code in Onion or Clean
Because it's the same thing
What about placing Automapper in Application layer? Doesn't that bind it with business logic? If at a later stage, another mapper or custom mapper is needed, it would require many changes to decouple old mapper and then implement new... Do you think it's better to have mapper in Infra ?
The chances of changing a mapper are slim to none
@@MilanJovanovicTech agree... They are slim but can't be ruled out... I had to recently replace Automapper with a more optimized mapper as my application was very large and Automapper was taking toll on memory... That's when I realized I needed Clean Architecture as Automapper was tightly engrained with every single project... Having it in Infra helps me as I can swap out very easily
hi Milan, thanks for these details. are the hexagonal architecture and onion architecture the same ? what about ports and adapters architecture ? thanks
I would say hexagonal is a bit "different" from an implementation perspective, more moving parts. But the result is pretty much the same, in terms of direction of dependencies.
@@MilanJovanovicTech thanks. Hexagonal is the same as ports and adapters i think
The previous video was clean architecture? Adapters were replaced with Infrastructure
Which previous video?
IMO both these architectures become a mess within a couple of days into development. We ditched them and switched to vertical slice architecture. It has been over an year now and we now maintain huge projects with ease. It would be great if you could compare it as well. Kudos to your work.
Within a couple of days? I've maintained CA/Onion systems for years, and they didn't become a mess. Maybe it's not the architecture, but the engineers...
@@MilanJovanovicTech "Maybe it's not the architecture, but the engineers...". Damn...
interesting. This is the first time I've seen anyone put the query handlers in the infrastructure (persistence) project. I've mostly seen the query handlers in the Application project which is also where the command handlers are.
Do you see an advantage to putting them there?
the only real reason is that your application layer doesnt need a dependency on the ORM when handlers are in persistance/infrastructure
Avoiding a reference to any persistence mechanism in the Application layer. And continuing down that train of thought, it makes sense. For a query I usually don't care how it's implemented, I only care about the result I get back. So I can move the details of that to Infrastructure. For command handlers, I definitely care about the implementation because it has business logic, so I want it in the Application layer. This is an idea I got from Jeffrey Palermo's Onion Architecture repo, and I just adapted it to MediatR.
@@MilanJovanovicTech So your repositories implementation only have the queries needed for the command handlers? And your query handlers use EF dbcontext directly I assume?
Frankly, though, I consider Queries a use case so prefer them in the UseCase (application) project.
So many ways to skin the cat I guess.
This goes very well hand in hand with the asymmetric approach DDD/CQRS follows. The write side of the application tends to be more strict and specific than the read side that can just fetch the data however it wants. Which would make the Domain project (Entites + Repositories) less significant for the read side.
@@kostasgkoutis8534Yes, I like the suggestion that there is a projection that matches each "view" in the UI so the query is nothing more than select * from CustomerSummaryView (or whatever)
But, I've never got to this point.
Свака част, феноменалан видео. Посебна похвала за пример, остали само теорију понављају... 60 секунди твог примера и све сам скапирао. Жив био.
Хвала пуно. Жив био. 😁
If you separate application service methods by class then it changes from onion to clean right? :)
It's the same thing, either way you look at it. Using services doesn't change the architecture
Do you have example project without clean arch. I need startup template with onion like your paid project@@MilanJovanovicTech
Thank you for this wonderful video. I have been using both architecture without having a clear understanding of the disticntion between the two architecture, and this video has cleared all grey areas. I noticed the Persistent project references the Domain project, is this allowed in clean architecture? My understanding is that only the application layer should reference the domain layer, but in your exmaple I see the "Article" object spanning across all layers up to the persistent/infrastructure layer.
IMO, they're the same thing 🤷♂️
Most useful videos, thank you Milan
Glad you think so!
Uncle Bob didn't tell us "how to implement Clean Architecture". so for me "Architecture" is just Onion. The concept of Clean Architecture could simply be called "Clean Code Design"
That's an odd take
@@MilanJovanovicTech It is simple, Clean Architecture does not strictly specify how to organize the outer layers. Onion Architecture, on the other hand, is more prescriptive about organizing the external layers, requiring them to contain specific infrastructure details, such as database access and UI.
Can't we put entities and repositories outside of domain and create a 2 separate layers among them?
Yes
@@MilanJovanovicTech Thanks! That won't impact the overall onion architectural style?
@@MilanJovanovicTech Thanks! That won't impact the overall onion architectural style?
Nice video and explanation but there isn’t much difference based on this tutorial. Just naming and package, for the onion architecture you used services and EFcore while for the clean architecture you used command and mediatr.
That was kind of the point ;)
Looks like I was implementing Onion Architecture instead Clean Architecture and I didn't know that. 😄
They're the same basically... 😂
Do you know any Java spring channel as good as this one ?
Nope :(
thanks for the video, how to access your sample codes? github?
Patreon or github.com/m-jovanovic
Thank you for the explanation, but I still don't see the difference. You've used MediatR in the Onion architecture, but not in the Clean architecture. Does using MediatR in the Onion architecture mean we've migrated to the Clean architecture?
That's because... the difference is pretty much non-existent
Apart from grouping features with folders what different thing does the clean architecture actually brings? It keep confusing me. Everyone implements it differently. I love onion. Simple and straight forward 😊😊
It's all the same thing, really...
Bro do you have any plans on making a videos series on an entire application from start to finish? frontend backend, db, containers, the whole 9 yards.
Yes, I did that in my course
@@MilanJovanovicTech
where can i find the course ?
Please explain too that Clean Architecture focuses on layering, while Onion Architecture focuses on inverted layering.?
They're the same :)
Did you need AsNoTracking() while projecting response using select new in clear architecture example?
Nope
Still using AsNoTracking while select immutable object. it's an indepence with clean architecute.
A great comparison and explanation, thank you!
Glad it was helpful!
Hey Milan, i have a question about Onion Architecture, you created a Article entity in Domain project, and you used this entity in Persistence project with ArticleRepository, this is not a problem because you are using a Code First DB but what if i use database first? My Article will be created with properties based on my database columns (SQLServer, MySQL, etc). This is a problem, because my Domain will be depends of Persistence
You can either:
- Use the scaffolded model, if possible, from the Domain (probably not possible)
- Map from domain to "persistence" model
- Add a DbContext that uses domain model, and can persist to DB?
Does anyone knows why the clean architecture doesn't represent the repository (repo interfaces) in its diagram
+ I didn't understand the point of making a requestQuery class in the usecases then injecting the dbContext and implementing it in the infrastructure
rather than just declaring GetArtictleByIdQuery method in the repo interface then implementing it in the infrastructure and using just like the other requests and request handlers in the usescases
It's all about direction of dependencies. Both architectures can be interpreted and implemented in different ways.
I like so much your approach by pratice. Thank you Milan.
Happy to hear that!
I personally would argue that mediator is part of a framework. That is why I am not using it, because every usecase class will depend on that library in the end. And use cases should describe pure business logic. I get why it is very convenient, but are you not a bit hesitant regarding the hard dependency?
No, not at all. Love using MediatR.
5:59 - IArticleRepository interface references your Api. Have a look at the top using statement. It's against either onion and clean architecture rules.
The same thing with the service in the Application library project.
No, that's just the namespace of the Article (which should be Domain.Entities though) 5:39
But the project references are correct.
You can grab the source code and check (pinned comment).
@@MilanJovanovicTech ok, that's make sense. Thanks for the video, bro.
I think it is confusing to have a use-case (GetArticleById) in the application layer, where you only define the query and the response, and the developer is expected to know to implement the handler in the persistence layer.
Wouldn't it be better to define a IArticleReadRepository interface, implement it in the persistence layer, and then implement the GetArticleByIdQueryHandler in the application layer, injecting the IArticleReadRepository into it?
Having an IArticleReadRepository defeats the purpose of GetArticleByIdQueryHandler. The GetArticleByIdQueryHandler becomes a wrapper calling an interface method. What's the value in that?
I made a video doing something similar: ua-cam.com/video/RgqCavV2cqQ/v-deo.html
You can see how silly it becomes
@@MilanJovanovicTech
Thank you very much for the link! I agree, it does seem pointless to create all this unnecessary abstraction with read services, if all we are doing is running a simple query.
isn't supposed that the GetArticleByIdQueryHandler in the persistence layer uses the ArticleRepository instead of using the ApplicationDbContext ??
Why would it?
Great video Milan!!
Thanks a lot :)
why not shared source code? so inconvenient :(
I share it on Patreon
Great video, Milan. Very practical info, rather to see your video to quickly be a up to speed, than reading a 500 pages Clean arquitecture book :P
Thanks !
Glad you enjoyed it!
Im little bit confused here. Onion focus on services and clean focus on use cases.
But service contains the use cases, isn't it?
Then What is the difference actually, Can anyone explain it.
They're the same thing 😁
@@MilanJovanovicTech 💔
Ah, after all you did this video! Nice!
Hope you enjoyed it!
@@MilanJovanovicTech sure, I enjoy watching your videos
Clean Architecture is not Domain-Driven Design?
It seems not
How to make a DDD architecture?@@magashkinson
How to make Domain-Driven Design? @@MilanJovanovicTech
You can combine both concepts easily
Onion, Clean, or whatever are just branding of the same thing. The most important part of this is the concept, not the implementation details or the name. Implementation might diverge and adapt to your needs.
Yes, you're spot on. I wrote about this in a few posts recently.
I think Clean architecture is more complicated than described in the video. Some key points - bounded context, domain objects are missed. Domain objects are completely different in onion ad clean, in clean you can`t simply take domain object and save it.
You don't need to use DDD to work with Onion/Clean
Yeah! This is a good point.
@@MilanJovanovicTech Yep, you are right, I messed up things.
Its the same, even the dotnet channel said it. "formerly known"
Formerly known?
@@MilanJovanovicTechthey probably meant dotnet channel mentioning Clean Architecture formerly known as Onion Architecture
I wanna add, that most design patterns (including architecture) are just a theory of how to do certain stuff. But its not a strict rule, so the Clean Architecture can be implemented with different outcomes.
I thought both are one in the same🙄
Its the same, even the dotnet channel said it. "formerly known"
By the end of the video, you can come to that conclusion
They are the same 😂
Cool idea to explain differences between those two approaches👌The layer is thin.. 😁
On a personal note I'm so glad CleanArchitecture has become more popular. I'll always remember the face of the people I tried to explain/sell "Onion" architecture benefits. Lost half of them right at the beginning 🧅🤥
Onion just sounds weird, that might be the problem 😅
👋
Thank you!
You're welcome!
Both are the same, the difference for me, is that one uses CQRS and another Services.. idk
Yep
In clean architecure the repository belongs to the application layer not the domain. The use cases should be exposed as inbound ports of the app layer and they should not be commands, they could however be implemented underneath as commands, but that's a technical detail that the caller does not need to know. A use case should also be named as Use Case at the end, for example AddOrderUseCase to make clear we are talking about use cases and not services or bananas. All the external dependencies of the application layer should be defined in a separate project called application.ports.outbound which is the one that the external layers will implement.
UseCase = Command/Query, same thing.
"All the external dependencies of the application layer should be defined in a separate project called application.ports.outbound which is the one that the external layers will implement" - Too much work for not so much benefit. We'll end up with dozens of projects if we go down this route.
@@MilanJovanovicTech not really the same thing mate. Commands and queries are a technical implementation of use cases
a VERY simple project. Why not show how a real world project is implemented... That will give a much better insigts in the real problems that you never need to handle in such simple examples..
Because the concepts get lost in the complexity of a large project, and you can't explain it all in a 10-15-20 min video.
@@MilanJovanovicTech I dont think so. Obviously you vcannot write that system from scratch but you can show diagrams of it and show exampkes of real code.
these kind of simplified examples doesnt really help. it just fools people.
Perfect❤
Thanks, glad you enjoyed it
Both architectures are trash and will be deprecated very soon anyway. But thanks for the video. (Liked)
Interesting take... why do you say so?
They've been saying that for almost 20 years now.
Is it the architecture that's trash or the project organization?
Code to interface not implementation is a pretty well-established OOP principle.
That said, why is it "trash"? Objective evidence, please.
Anyone saying this has no Idea imho! 😂 sorry, but this architectures keep the most basic and ever important keypoints. You will always have to deal with dependencies and layers. Have Met alot of people saying the same, watching their "architectures" and know whats their problem.. they are mostly beginners, although few of them programming for tons of years.
nothing is trash when u really understanf the idea behind it