How to structure a .NET Solution (project separation & architecture)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody i'm nick in this video i'm going to show you how you can structure your.net solution into multiple projects that make sense and keep your application layered and well structured in this specific demonstration i'm going to be using jason taylor's clean architecture solution but this is not just the only way you can do it it's just my personal favorite way and i've actually been using it for the past three years with great results that's why i want to share it with you in case you are not aware of it there is also steve smith's clean architecture project but i personally align more with jason taylor's one that's why i'm going to be examining that in this video however there is no right and wrong as long as you can keep your code clean and well structured i've worked with projects that the whole solution was one project but developers were so in line and they were so good at knowing what to use where that the project never implemented any code smells or crossed any boundaries however physical splitting will help with that that being said i've also seen excessively split solutions in multiple projects which really should have been folders which is also very problematic so in this video i'm going to show you what i think is the golden line between one project and oversplitting so what i have here and this is very important actually before i show you the projects themselves is we have two top level solution folders these are very important they give structure to our application and they split the test project from the actual source code i always have them and i definitely recommend you to have them now the docker compose ignore it is just there because ryder identified that this solution has some docker files in it that's fine ignore it for now what we care about is the source and the tests first we're going to go to the source and as you can see we have four projects and these four projects represent three different layers those four projects are in order of from inside to the outside domain application infrastructure and web ui the web ui is also called the presentation project or the presentation layer and it's supposed to be the way you interface your application so in this scenario web ui is an angular application but it could very much be a traditional mvc it could be a blazer up could be a desktop application it could be anything but it's supposed to be the top layer that your customers are going to interact with your project now why is the project split like this and what are those projects supposed to represent i'm going to pull up an image here and this is what i want you to think about when we're going through these projects in the very core of your application you have the domain layer and this domain layer which is represented by the domain project in our solution is supposed to store any enterprise-wide concerns things like types entities exceptions things that are used across the whole domain not specific to the application that we're working on but domain specific so if you're working in finance or your finance specific things would go here things like currency effects rates the way you represent them they all go in there you use value objects uh to combat primitive obsession as well in those scenarios so it's a very domain driven approach if you think about it but it doesn't have any logic for your application per se in that layer it's more about the objects themselves and the entities themselves the exceptions and the way you want to represent that in your code so any domain logic goes there then you have the application layer which in our solution is the application project and the application layer has concerns specific to what it's supposed to be doing for example if it's a service that is supposed to return you the effects rate then all that logic on how to do it lives in the application but the types themselves live in the domain so the application is the layer where you are defined the abstractions for example the ifx service should go there but not the implementation keep that in mind it's important it's only dependent on the domain layer so it will use the fx rate domain object from the domain layer but in the application layer you will only have things on okay how can i do what my application is supposed to do in this layer you have when i say this having an application you have to define your abstractions and you can use those abstractions with dependency injection in your code however the how you can do that for example how you can go to the file system and grab something how you can go to your identity provider and grab something how you can go to your persistence layer like your database or how you can call an external service like an fxraid service that would go the implementation of that would go in the infrastructure layer and let's see that in this project so i'm gonna expand the domain and i'm going to show you the empty this folder this is a to do list and to do item project so here we have two domain entities which are the to-do item representing a to do item and then you have the to-do list which is representing a to-do list go figure and those are just domain level entities and things like domain level exceptions as well for example an unsupported code exception which is enterprise wide would also go in here but as you can see there is not much in here other than a few objects and then a few very core like domain event abstract classes in the value object definition and this is the idea of the domain option it's supposed to represent the core of your application and address any enterprise wide concerns i cannot stress that enough you don't want to have application specific implementations here this project also doesn't have any external dependencies and when i say external dependencies i mean from the other projects you want this to be the core of your obligation so it's isolated then you have the application layer of the application project and that project does depend to that domain layer only this project will implement how it can use those enterprise-wide concerns into a meaningful way for example we have a command which is called create to-do item by the way this project is using mediator and cqrs we've talked about this in this channel if you wanna check that out after this video ideally click on the top right corner of the screen and you can go there so here we have a command which is an i request from mediator and then how we can use that command to create a to-do list item is here but we do not have the implementation of this iaplicationdb context here the interface the abstraction lives in the application layer in fact i can show you that this is in the clean architecture dot application layer but nowhere to be found in this project do we define how it can do it and the reason for that is because implementations for those external concerns should go in the infrastructure layer and why do we do that well the infrastructure layer directly depends on the application layer to implement those abstractions and we do that because if for example in the future i want to change from an entity framework and i want to use cosmos db for example or if in the future i want to change my identity provider and instead of using the asp.net core identity i want to use identity server or when i use octa the application itself the interface the abstraction will not change my application will still need to do those things defined in my contract that is the interface however the implementation because it can be fluid based on swapping out the tools that we're using can be externalized into another project and we only have to deal with that external project when we need to make changes leaving our application layer unaffected and this abstraction in my opinion is the most important in this grand scheme of things because it gives you the peace of mind that if you clearly define what your application needs to do it doesn't matter what the implementations will be you can change them later and as long as the core idea is unit tested and tested in general it doesn't change and it doesn't break based on the tools behind the scenes so again any application specific concerns and only application logic specific concerns go into the application layer but any implementation for those concerns go in the infrastructure layer and then you have the presentation layer and the presentation layer depends on two projects it depends on the application layer and it depends on the infrastructure but and this is very important the only reason why it depends on the infrastructure layer is to do service registration on the startup.cs for no other reason and in no other place should you refer to clean architecture dot infrastructure or in general the infrastructure project in any of the other places of your presentation layer and this is very important this is a constraint you have to put on yourself because it could actually cause issues of you crossing boundaries what i like to do personally in that scenario is i use a very similar approach where json is allowing you to use public static service registration extension methods to automatically do your registration without actually knowing how to do it so all your startup.cs needs to do is like dot add infrastructure and then to register all that i personally like to mark things in the infrastructure layer as internal when they don't need to be used by anything external and then i only register them in this method so even if you try from a web ui or representation layer to do something that crosses the boundary you cannot because the internal keyword won't allow you to do it but that's just how i like to do things so again to take a look back at our image here the domain layer is the heart of your application addressing enterprise level concerns the application level is addressing application specific logic and concerns but it doesn't implement any of that logic when it comes down to the services that you're using to implement it of course what your application should do will go there so application specific concerns an application specific logic will go there but external matters like database file system network calls to external services they would all go to be implemented into the infrastructure layer even though they are defined on a contract level with an interface on the application layer and then presentation is only depending on the application and we had to also depend on the infrastructure but only for service registration remember that and by doing that we're achieving a very safe and clean structure when it comes down to addressing concerns and responsibilities in separate layers and then what you have is the project's solution folder which i also use a lot which is the idea of having one project per type of tests per project let me rephrase that the application project for example has unit tests and integration tests so what i would do and what json does here as well is i would create a test project pair type of tests per project so application dot integration tests all my integration tests for the application project goes there then application dot unit tests all my unit tests for the application project goes there if i had more like if i wanted to do some jerking acceptance testing and bdd application dot acceptance tests would be there to have all the exceptions for my application so that's another very nice way which i think people overlook and sometimes they smoosh integration and even tests into one project and they just call it tests i don't like doing that what i'm personally doing by the way when it comes down to naming is i say application.tests.integration and application.test.unit but that's just semantics it doesn't really affect how you structure the project another thing about this project splitting is that i would usually if the web ui or actually the presentation layer is an api i would have a separate project for my contracts requests and responses and in my ci i would also publish that as a nuget package so it can be reused by other teams in the company or it can be reused by other projects and if this is a grpc which has a client or an api that has a client or an sdk effectively to call it i would also have that sdk here with a dot sdk or dot client and those projects would depend on the contracts which i had split in a separate project that's all i had for you for this video thank you very much for watching special thanks my patreons for making these videos possible if you want to support me as well you're going to find a link in the description down below leave a like if you like this video subscribe for more content like this and ring the bell as well and i'll see you in the next video keep coding
Info
Channel: Nick Chapsas
Views: 87,555
Rating: undefined out of 5
Keywords: Elfocrash, elfo, coding, asp.net, .netcore, dot net, core, C#, how to code, tutorial, asp.net core, csharp, development, software engineering, microsoft, microsoft mvp, .net core, nick chapsas, chapsas, how to structure .net project, .net solution structure, project spliting, clean architecture, clean code, jason taylor, How to structure a .NET Solution, dotnet, .net
Id: YiVqwoFMieg
Channel Id: undefined
Length: 13min 54sec (834 seconds)
Published: Mon Feb 01 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.