Clean Architecture With .NET 6 And CQRS - Project Setup

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone my name is milan and today we are talking about clean architecture the first part of this video is going to focus on the why of the clean architecture and in the second part i'm going to show you a project setup using the clean architecture and we will see some implementation details let's first start out with what is the clean architecture here you can see the visual representation of the clean architecture it has four distinct components and these are called layers of the clean architecture in the center of the clean architecture we have the domain layer which represents the core of the system around the domain layer you have the application layer which orchestrates the domain layer and tells it how to perform the business logic and on the outsides of the architecture we have the infrastructure and presentation layers i'm going to start from the core of the clean architecture and we will move outwards in the center of the clean architecture we have the domain layer in the domain layer we will typically define things like our domain entities containing the most important business rules here you can also see things like aggregates value objects domain events if you are using domain driven design then we can define repository interfaces factory interfaces domain services and so on this is also a good place to define your custom exceptions the only rule that you can't break in the domain layer is you cannot reference any of the outer layers the outer layers are allowed to reference the domain layer but the domain layer cannot reference any other layer in the architecture moving one level up we have the application layer this layer acts as a sort of an orchestrator for our system in the application layer we will define our most important use cases typically this layer is implemented as a set of application services or if you are using the cqrs pattern here you will see commands and queries this is also the approach we will see in the practical example a little later in this video on the outsides of the clean architecture we have two layers that are seemingly on the same importance i will first talk about the infrastructure layer here you will see anything that is related to external systems in the infrastructure layer we define things like database access message queues so things like revit mq or kafka email and notification services storage services and so on the infrastructure layer is responsible for hiding the implementation details for any external systems that we need to integrate with and lastly the presentation layer is used to define an entry point for outer users to be able to interact with our system typically the presentation layer is implemented either as a restful api or maybe even something modern like grpc i hope that i didn't bore you with the foundations of the clean architecture so let's move on to the code and see how we can set up a project using clean architecture now that we are inside of visual studio let's talk about how we can implement the clean architecture you will notice that i have four projects here that exactly match the layers of the clean architecture that we just discussed inside of the core folder we have the two inner layers domain and application and inside of the external folder we have the infrastructure and presentation projects let's go over them one by one and see what we have inside i will start from the domain layer as you can see we have an entities folder defining the entities of our domain in this case we have only one entity which is a webinar a webinar is a simple class with an id a name and the date when the webinar is scheduled on you can also notice that the webinar inherits from the entity class so let's see what we have inside as you can see the entity class is very simple it only contains one property which is the id of the entity in domain driven design two entities are considered equal if they have the same identifier even though the object reference might be different one other thing that we have in the domain layer is the custom exceptions here we have one custom exception for when a webinar is not found this exception is thrown from the application layer when we attempt to fetch a webinar from the database that does not exist i'm also going to go over the abstractions folder here you can see i have an interface for the webinar repository notice that this is only an interface and the implementation is in one of the other layers and there is also the interface for the unit of work if you want to implement the unit of work pattern this is where you would define the interface and the implementation would most likely be in inside of the infrastructure layer so as you can see the domain layer is very simple we only defined one single entity a couple of interfaces for the repository and unit of work some custom domain exceptions so now let's move on over to the application layer and see how we can use what we defined in the domain layer i'm going to close this up in the application layer i will start from this webinars folder you can see that we have separate folders called commands and queries i mentioned that we are using the cqrs pattern here cqrs stands for command query responsibility segregation it's a very popular design pattern where you split the flows for reading and writing data into separate paths let's start from the command side we have one single command create webinar and inside of this folder we have a couple files i'll start from the create webinar command this command contains all of the data that is necessary to create a new webinar you can see all we need is a name and a scheduled on date then we have a command handler which handles this command inside of the command handler we have the handle method which will create a new webinar use the webinar repository that we defined in the domain layer to insert a new webinar called the save changes on the unit of work which will complete the database transaction and it will return the id of the new webinar on the query side we have one query which is get webinar by id you can see that this query only needs the webinar id to be able to return a response and this query is handled inside of the get webinar query handler here we are taking a different approach because we are reading data from the database to display it to the user we want to be a little bit more performant so we don't want to deal with repositories and unnecessary abstractions which is why we are writing raw sql executing it on the database fetching the data that we need and returning that response to the user inside of the application layer you can also introduce some crosscutting concerns here i am using a library called mediator for the cqrs pattern implementation and meteor has a concept of a pipeline which is very similar to the middleware concept that you are used to in asp.net what mediator allows us to do is to implement a pipeline behavior which allows us to wrap our command or query handler and execute some accompanying logic in this case we are validating the commands that we send using mediator and if there are any errors with our commands we throw a validation exception it's important to note that this exception is handled in some of the upper layers which i will cover in just a moment let's move on to the infrastructure layer i'm going to close down the application layer and open up the infrastructure layer you can see that here i define my db context since i'm using any framework for database access you will also find the repository implementation which in this case is very simple because we only have one single method for inserting a webinar to the repository then i have a folder for database migrations and the entity configuration for nad framework if for example on the query site i need to read the data from a replica database the implementation details for talking to that database would reside inside of the infrastructure layer it's also very common to see the infrastructure layer split into two separate layers we would have a persistence layer that would handle anything related to database access and then the infrastructure layer would handle other external systems like email notification message queues storage services and so on let's check out the last layer which is the presentation layer and here you will see something unusual you can see that i have controllers defined outside of the web application which is what you might be used to and i'll go over the controller implementation very briefly we have one endpoint for getting the webinar it accepts a webinar id creates a new get webinar by id query it sends it using mediator and returns the response of the query the other endpoint is create webinar it accepts a create webinar request from the body of the http request it then maps that request to the create webinar command here we are using mapster as our mapping library we then send the command using mediator again and we return the id of the newly created webinar now you might be wondering why do i define my controllers outside of the web application so let me explain that part to be able to support dependency injection you need to define all of your service registrations inside of the web application this then means that you have to reference all of the projects that you have in your solution and if you also have controllers inside of the web application that means that the presentation layer which is our controllers will have access to anything that is defined inside of our application imagine that the webinars controller was indeed inside of the web application and we have access to the infrastructure project now i can go ahead and do something like this i can define a new field inside of the webinars controller and this field is going to be the application db context then i can go ahead and inject this field using dependency injection and this will function this will work just fine i can then proceed to use the database context inside of my endpoints for data access and so on and this completely breaks the cqrs implementation that we are using for reading and writing to the database so if our controllers were defined inside of the web application we wouldn't have a way to enforce the architecture but if we move the controllers into the presentation class library we can control what other projects we are referencing and this gives us complete control over our architecture which is something that more junior engineers aren't thinking about let me also show you the one piece of configuration that you need for controllers to be able to function outside of the web application i'm going to open up the startup.cs file and at the start of configure services you can see that we are assigning the presentation assembly which is where our controllers are defined to a variable we are then calling services.addcontrollers which will add all of the necessary configuration for controllers to be functioning and then this part is key we call the add application part method and we pass in the presentation assembly which is where our controllers are defined and now the web application will be able to pick up the controllers and configure the routing and everything will work just the same i'm also going to show you one more thing inside of the web application inside of the middleware folder you can see that i defined an exception handling middleware class and all this class does is it wraps the execution of our application with a try catch block it catches the exception logs the error and then returns the appropriate response to the user so if you want to create a custom envelope for api errors you can do that here i suggest using the problem details response because it's more standardized that was a quick overview of the project setup for the clean architecture in one of my future videos i will go over the implementation steps of the clean architecture we will start from the domain layer and then we will move up through the other layers of the clean architecture if you use the clean architecture before let me know in the comments how this worked out for you if you like this video make sure to give it a like subscribe to my channel so that you don't miss any of my future videos and until next time stay awesome you
Info
Channel: Milan Jovanović
Views: 145,777
Rating: undefined out of 5
Keywords: clean architecture .NET, clean architecture, .net architecture, .net, .net core, dotnet, dotnet core, software architecture, clean software architecture, cqrs, mediatr, .net mediatr, .net core clean architecture, .net core architecture, clean architecture setup, .net core project setup, dotnet tutorial, dotnet 6, dotnet core web api, dotnet core 6, dotnet core tutorial, dotnet microservices, mediator pattern, mediatr pipeline behavior, clean architecture cqrs
Id: tLk4pZZtiDY
Channel Id: undefined
Length: 12min 40sec (760 seconds)
Published: Thu Aug 11 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.