[0:00] hey everybody it's derek martin from [0:01] codopinion.com a lot of people have [0:03] asked me directly or indirectly about [0:05] the clean architecture in my opinion [0:08] some people have asked me directly and [0:09] pointed out to jason taylor's c-sharp [0:11] template while others have asked me [0:13] indirectly because of the code samples [0:15] that i have in some of my other videos [0:16] where i don't apply it so here's my [0:18] opinion and thoughts on clean [0:20] architecture templates where i see the [0:22] value and where i don't so let's cover [0:24] the clean architecture really quick and [0:26] just describe this diagram which you've [0:28] probably seen this is from robert [0:29] martin's blog in 2012. the very middle [0:32] is essentially the core is our domain [0:35] this is where our business rules are [0:37] outside of that our use cases these are [0:39] our application how it's invoking those [0:42] actual [0:43] domain objects those entities then you [0:45] have things like controllers if you're [0:46] doing something like mvc or gateways or [0:49] presenters for ui but again this is one [0:52] step further where this is what's [0:54] actually interacting with calling those [0:56] use cases and above that is all things [0:59] external so if you're generally creating [1:00] a web app this is where the web host is [1:03] going to live if you're creating a [1:05] native ui app this is where that ui [1:08] framework lives but the key thing here [1:11] are these arrows and these arrows are [1:14] really pointing inwards that's why i [1:16] have dependencies point inwards because [1:17] that's really the key to all of this [1:19] is that outside layers can reference [1:22] inside layers but inside layers don't [1:24] reference outside layers so if you watch [1:27] my video on coupling specifically [1:28] talking about afferent and efferent [1:30] coupling so afrocoupling being who do [1:32] you depend on in effort coupling being [1:34] who depends on you [1:36] is why this is important is because that [1:37] the very big at the very center here [1:39] with our domain and our entities [1:41] who depends on you for afferent coupling [1:43] well the use cases does [1:45] who do you depend on efferent coupling [1:47] nobody nothing is that you don't depend [1:50] on anything you have no dependencies [1:51] within entities and as you go out that [1:54] starts reversing so [1:56] a lot of this to me and about clean [1:58] architecture is about dependencies and [2:00] having that core have no dependencies [2:03] things depend on it but it does not [2:05] depend on anything else so a lot of [2:07] people pointed me to this specific [2:08] template this is the c-sharp template [2:10] clean architecture by jason taylor so [2:12] this is going to what i'm going to use [2:13] as my example so this is what the actual [2:15] solution looks like there's four [2:17] projects application domain [2:20] infrastructure and web ui so what that [2:22] looks like from the diagram is the [2:24] outside here web ui is asp.net core [2:27] it references infrastructure and [2:29] application [2:31] infrastructure is the project that [2:33] contains like the db context for nad [2:35] framework and any implementations of any [2:38] services [2:40] the application is handlers in commands [2:43] and queries that's using mediator [2:46] and then it is referencing the domain [2:48] and the domain is our entity framework [2:50] entities so first let's talk about [2:52] templates for a little bit because i [2:53] have a love hate relationship with [2:55] templates and because it falls into the [2:58] only issues i have with my own code [2:59] which is providing examples that are [3:01] simple that people can understand and [3:02] hopefully the concepts behind it so that [3:05] they just don't run away with it and [3:07] keep doing the same thing that they [3:08] understand their context to see if it [3:10] actually fits [3:11] that's the problem i have with templates [3:13] is that this is a to do list kind of to [3:17] do item [3:18] sample that it's using to illustrate [3:20] this which is super simplistic and [3:23] exactly i understand this is a template [3:25] it's an example that's why it is simple [3:27] but the problem is again people going [3:29] with this and running wild with this [3:31] when if you're creating a [3:33] a smaller type of application do i think [3:36] you need to do clean architecture no [3:39] i'll explain why more shortly but i [3:41] don't think you need to so depending on [3:43] the size of your app i think there's [3:45] benefits um to the clean architecture [3:48] i also think there's a time and a place [3:50] for it depending on the complexity and [3:52] the size of your app so what i'm gonna [3:54] do is go through this template and i'm [3:56] not criticizing the template so much as [3:59] i am just trying to explain what i think [4:01] actually belongs in each project if you [4:03] have that project again it's this is a [4:06] template it's a sample so i don't expect [4:08] it to have a ton of complexity to [4:10] illustrate really the nuance of why you [4:12] want clean architecture so the first [4:14] thing i looked at when i opened this [4:16] project was this domain project and this [4:19] is the very center of the core it has no [4:21] dependencies so it preferences no other [4:24] projects and when i was looking at it i [4:26] wanted to see what the if there was if [4:29] it was doing some aggregates if it had [4:30] entities whatever the case may be [4:33] and ultimately what it was is it has [4:35] this to do item and to-do list [4:37] which basically are our entity framework [4:40] entities there's basically no behavior [4:43] on here at all why would you expect [4:44] there to be any it's a to do [4:46] but that's the part where it gets lost [4:49] is again if people are using this as a [4:50] template they think oh this is where my [4:52] entity framework entities go and while [4:54] it's true that you can have your entity [4:56] framework entities live in the domain [4:58] project you can have the infrastructure [5:00] project which i'll show here has the db [5:02] context the entity framework db context [5:04] and it's referencing it and it's using [5:06] them [5:07] i would expect my domain project to [5:09] actually have business rules and again [5:12] this is a simple example so there are no [5:14] business rules but my domain project is [5:17] the core of what my application is it [5:20] should be the one containing all the [5:21] business rules this example template [5:24] displays none of that it illustrates [5:26] none of that [5:27] so if you weren't aware of that's the [5:29] point of the domain in your entities and [5:31] if you're creating something like [5:32] aggregates that are consistency boundary [5:35] check out my video on that [5:36] that's where this would live but just [5:38] looking at this template you wouldn't [5:40] know that all right so the next thing to [5:42] look at is the application project so [5:44] this is the one that's referencing the [5:46] domain so it's a layer above the domain [5:49] so the things that it has in it that are [5:52] somewhat interesting i guess in what i [5:54] like about having kind of this [5:56] application layer is it's the one that's [5:58] actually going to invoke and call stuff [6:00] within your domain so [6:02] there's this to do items folder and to [6:04] to-do list folder and it has everything [6:07] separated for commands queries and event [6:10] handlers [6:11] now i'll talk a little bit more about [6:13] this technical separation later on how i [6:16] prefer it but i do overall like this [6:18] approach [6:19] as you maybe have seen in some of my [6:21] other videos but one thing i really find [6:24] interesting is that the application uh [6:26] this particular project is going to [6:28] define interfaces just interfaces not [6:31] the implementation for things that it [6:32] needs one of those things it needs as [6:35] you can expect is a [6:38] entity framework context [6:40] so instead of referencing the actual db [6:42] context that's being used directly [6:44] rather what it interacts with and uses [6:47] is this eye application db context so [6:50] the reason why i find this interesting [6:52] and why i don't generally follow this [6:54] approach is because of a leaky [6:56] abstraction [6:57] and this is showing it whether you [6:58] realize it or not yet right now so [7:01] the infrastructure project is what [7:03] implements all the interfaces defined in [7:05] the application [7:07] uh the application project so if i look [7:09] at infrastructure i go down there is a [7:11] persistence and application db context [7:14] so here's our actual entity framework [7:17] uh db context that we're using [7:19] and it implements that interface [7:22] so when i look at that interface the [7:24] idea here on the application is it is [7:26] kind of lost on persistence it doesn't [7:28] really know how it does it doesn't [7:30] necessarily know that it's entity [7:31] framework right we just have these lists [7:34] well actually it does know it's entity [7:36] framework because it's using these db [7:38] sets and these db sets are directly [7:40] coming from entity framework [7:43] actually this application project has a [7:46] reference to entity framework so i'll [7:48] ask you the question if you're going to [7:50] have a leaky abstraction or you try to [7:52] want to ignore what your persistence is [7:54] you're not really doing it with this [7:56] approach especially how this is anyways [7:58] so you may be screaming well use the [8:00] repository pattern i'll save that for [8:02] another video because that's a whole [8:03] different topic so i'm all for [8:05] abstractions the right abstractions and [8:08] most times i think external services i [8:10] think are really good to abstract [8:12] because you can kind of narrow the focus [8:13] of what that abstraction does and what [8:15] you need it for but when you're doing [8:17] something like entity framework or data [8:19] persistence i think you lose a lot and i [8:22] generally don't think you actually need [8:24] it i say that because if you're creating [8:28] small applications like this or smaller [8:31] little components which i'll talk about [8:32] in a minute [8:34] you don't actually need the abstraction [8:35] because the actual cost of rewriting [8:38] where that data access is is so low it [8:40] wouldn't really even matter you don't [8:42] even need the abstraction [8:44] and secondly if you're gonna actually [8:46] create an abstraction [8:48] what are you losing by using the direct [8:51] client or sdk that you're interacting [8:53] with if you don't have a really narrow [8:54] focus and you need to use a lot of it [8:56] then you're just trading more and more [8:58] into your abstraction to fit it [9:01] if it's something really critical to you [9:03] just use it there are exceptions to the [9:05] rule i mentioned this in other videos [9:06] messaging libraries give you a lot of [9:08] functionality that you otherwise [9:10] wouldn't get from the client or sdk [9:11] directly that you have to implement [9:13] yourself so those are the type of [9:14] distractions that you do want but you're [9:16] not creating them you don't own them [9:18] you're using messaging libraries for [9:19] this all right so the last project to [9:22] look at is the web ui project so this is [9:24] the very outer edge this is asp.net core [9:27] and we have some controllers in here as [9:28] you might expect so let me jump into the [9:31] to do items controller [9:32] and you can see that it has some various [9:34] actions for kind of crud related things [9:37] um that we need to interact with for our [9:39] to-do item now the reason why i don't [9:42] actually like controllers in general is [9:44] because they have really low cohesion [9:47] and especially even more is that um all [9:49] these particular commands here this [9:51] create create to do item command [9:54] this is exactly a one-to-one like this [9:57] particular action in this controller [9:59] maps directly to the command and command [10:02] handler this is the only place at all in [10:04] solution besides tess [10:07] that this is actually ever created [10:09] there's no other place that's creating a [10:11] to do item there's no other place that's [10:13] invoking it anywhere calling send on it [10:15] it's simply here so the reason why i [10:18] don't like this is because i much prefer [10:20] having things close together i don't [10:22] want to have to jump through projects [10:24] and files i would much rather see [10:27] everything that belongs together is [10:29] together and i can go into one location [10:32] and look at basically everything so when [10:34] i say group things together i'm [10:36] generally less concerned about layers [10:37] for an entire application and more [10:39] thinking about features and [10:41] functionality [10:42] and kind of the concerns within that [10:44] feature so i'm less concerned about [10:46] abstractions and i'm more concerned [10:47] about just what a feature does and [10:49] letting it define its dependencies and [10:51] whether it needs an abstraction or not [10:53] so instead of thinking about the whole [10:54] layers i'm thinking about what's a [10:56] particular subset of features and let's [10:59] pull out the important parts and put all [11:01] that stuff together so well instead what [11:04] it really looks like is maybe i have two [11:06] web ui pieces which are really the [11:08] controllers that's interacting with say [11:10] the same infrastructure which maybe [11:12] could be the certain db context which [11:15] interacts with our app which is our [11:17] mediator commands or queries and [11:19] handlers and maybe those two particular [11:21] features share a domain but i'm [11:23] organizing code that way i'm not [11:25] organizing code necessarily by layers [11:28] that's happening in that template so [11:30] taking that concept and consolidating it [11:32] what this means is i have two projects [11:34] now not four [11:36] i have the outermost which is the web ui [11:38] which is asp.net core and i have to [11:40] define this as kind of the entry point [11:42] this could be asp.net core this could be [11:44] a [11:45] native ui this could be like a service [11:47] that's interacting with your your [11:49] message broker that's going to be [11:50] invoking into your application this is [11:52] kind of topmost entry points but i don't [11:55] actually have any of the controllers [11:57] here [11:58] really the controllers are living in [12:00] their respective features so i now have [12:02] a folder called features and i have [12:04] these to-do list items and [12:06] lists and items [12:08] and instead of having a file for [12:12] basically commands and queries like it [12:14] was earlier and event handlers i left [12:16] the event handlers in here because they [12:17] don't really do anything normally these [12:19] would actually just be a part of this [12:21] name to what they actually do [12:23] but if i jump into the create to do item [12:26] here it has the controller here the web [12:29] ui is referencing this it's [12:30] automatically going to pick up this [12:31] controller i have the relevant mediator [12:34] command [12:35] the validator for it and the relevant [12:37] command handler [12:39] since it's publishing an event i [12:41] actually have the event here as well so [12:44] when i'm talking about or thinking about [12:45] anything to do with an actual command [12:48] everything resides in one file it's one [12:52] place now often the argument is well now [12:54] you're referencing asp.net core in this [12:56] application project but it really only [12:59] needs to be in the web ui true that is [13:01] true however [13:03] if you do create some other service if [13:06] you do [13:07] that doesn't need asp.net core well yes [13:10] you will still be referencing it and it [13:12] just won't do anything that's a price [13:14] i'm willing to pay to have code that [13:17] belongs together live together so that i [13:19] can access it directly and understand [13:22] instead of jumping through projects and [13:24] layers i have things closer together so [13:27] you'll notice i took out that domain [13:28] project and the reason is is because [13:30] there was nothing meaningful in it if i [13:32] was creating a rich domain i did have a [13:34] lot of complexity around my domain and i [13:37] wanted to create a separate project so i [13:39] didn't have any other dependencies that [13:41] i could focus specifically on that [13:42] domain to create entities values objects [13:45] aggregates then yeah that'd be a great [13:47] idea in this example for illustration [13:49] purposes there wasn't anything [13:50] meaningful in it so therefore what's the [13:52] value of having that project so the [13:54] value to me in separating by project is [13:56] if you want a hard physical boundary [13:59] with dependencies an example of this is [14:02] that you don't want to accidentally put [14:04] say some type from asp.net core in a [14:07] mediator command or query because if you [14:09] do need to rip that out well now you are [14:11] actually bound to asp.net core because [14:13] you have that reference in there in the [14:15] original template you wouldn't be able [14:16] to do that so again yes it is about [14:19] context it is understanding what you're [14:21] doing and what types you're using where [14:24] if you want to accomplish that by having [14:26] the boundaries of projects and layers [14:29] excellent that more power to you [14:32] if you can see past that and you [14:33] actually want to create slices where [14:35] you're depending less on abstractions [14:38] and creating smaller units where you can [14:40] refactor those and pull those out [14:42] separately then to me there's less of a [14:44] concern about those abstractions because [14:46] if you need to replace them what the [14:48] actual underlying implementation is with [14:50] something else you can do it so for [14:52] everybody that's been asking me about [14:53] this i hope it helps if you found this [14:55] video helpful give it a thumbs up if you [14:57] have any thoughts or questions make sure [14:58] to leave a comment and please subscribe [15:00] for more videos on software architecture [15:02] and design thanks [15:23] you