SOLID IS OLD!! - Dependency Inversion Principle

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
solid old it is old polymorphism it is watch this video [Music] embrace the dark side you will embrace the dark side all right let me explain what you just heard what's up youtube today's video is about dependency inversion dependency inversion being the d in solid and so as you heard before solid old it is what i'm trying to say there is of the solid acronym i don't care for the s and i don't care for the i the i is i think it's most obvious right it's not something that you have to it's not it doesn't it's not in the same league as i said the d is all right so the d i think is the the most prominent one of the two unfortunate comes at the end the eyes it's it's nice to know but it's not in the same league right it just doesn't belong in this acronym at that level now so what is when i say solid old it is i mean by the way i'm hoping you guys know this is yoda speak from star wars in case somebody don't the newer generation doesn't know what that is so old the acronym or ld open close principle list of substitution principle and dependency inversion old polymorphism it is which is essentially polymorphism right i think there's so much of i don't know ceremony and you know kind of importance given around some things that are so old literally old meaning but you can't blame them right this is when this list called substitution mr barbara liskov came up with this idea of abstract data types where this was before polymorphism right and it is a big deal to say that you could treat data types uniformly in a uniform fashion as long as they conform to a certain let's call it an interface that was the beginnings of or if not the that's what they considered polymorphism at the time so it was a huge deal in the 60s 70 like was a big deal it's just polymorphism right i mean you can come up with the mathematical formula that she comes up with and all that but that it is just polymorphism let's just leave it the way it is open close principle but i'm not going to be talking about open close principle and this cough substitution principle then in depth here it's just a matter of explaining to you why i consider old polymorphism it is open close principle it's well you could there's a way to look at it as a form of inheritance which is also unique in those days by the way it's just you know unique in terms of the we didn't have object-oriented programming when we did it was so new that you had to literally tell people how to write code right they came from a different paradigm structured programming paradigm so this was more like giving people the basic basic basic training wheels of object-oriented programming this is not such a big deal i mean maybe yes you know i do recognize that there are a lot of us that don't understand polymorphism sure but that's the industry as a whole it's not struggling with polymorphism today back in the day they were back in the day it was more like you had to introduce them to things that they have never seen and heard or thought of before right so any open close principle could be seen as a form of inheritance of people in inheritance for the sake of extension which is something as you know i don't do i don't inherit for the sake of extension but open close principle would say you know open for extension would mean either through polymorphism or through extension through inheritance purely simply extending the base class the descending class to have more functionality than the base class hover list of substitution principle is essentially saying you cannot or should not be using inheritance for the sake of extension you want to use inheritance for the sake of interfaces in terms of abstract public surface such that you can treat all descendants in a uniform fashion at the call side which is polymorphism dependency inversion well it's not that dependency inversion itself is polymorphism but when you invert dependencies you are effectively using polymorphism if you know if you're doing things correctly so that's like saying that solid all it is really trying to do is trying to tell you you need to be using polymorphism and that that's exactly true that is exactly what it is now single responsibility i don't know about that i mean i i can see somebody trying to give someone a set of instructions to follow when you're when you're new to programming right you kind of need certain guidances and instructions at the beginning but i'm not sure that i would design systems you know say oh my system is all srp and that's actually the the problem i have with solid is but i'm going to write a little bit about solid hopefully i'd rather do this again and again this video is about dependency inversion okay so let me tell you what we're going to do today i'm going to introduce to you the dependency inversion principle we're going to look at a lot of code it's going to be a little quite a bit in depth but that's the reason is that you know i need to kind of show you with code what i mean some of the code most of the code will be available on my github so in case you need to refer to that code again you have the option but today's video is focused on dependency inversion and by way of extension point and abstraction right and so i'm gonna sort of marry these two things dependency inversion and abstraction in this video and tell you why i think that's gonna you know the the important aspects but we're gonna be looking a lot of code but i'm gonna also doing be doing a bit of this ranting so i don't know about you all or those who are trying to learn solid what you're thinking or what you're imagining is going to happen when you run sorted or understand solid every time i've talked to someone who has supposedly implemented their system using solid principles right it's like a given okay i listen i have implemented the system using solid principles that's like saying okay so my system must be right i mean you cannot find fault in my system right i don't know where they get this from i don't know why they feel that way but it's almost like if you're using solid principles you must be doing something right or the other converse of that is you can't be doing anything wrong [Music] they shouldn't have been called principles by the way i think that's just looking like a bad you know terminology there but first of all if you put 10 people in a room i can almost guarantee you if you ask them please explain sort of the different principles right s or l they will each have their own version of it understanding of it even if they have the same explanation their implementations will be completely different but completely different i mean they're [Music] all correct i just mean they're different and many of them would be wrong if not all of them will be wrong my problem with solid is the phrases you know single responsibility class should have only one reason for change and why has it taken decades i think i think bob martin published this article in early 70s um i think in the early 70s it was before my time soon i don't know [Music] either ways it's taken decades he's still teaching people the same thing right they say why is it that it's such a because they're so right obtuse these descriptions are so big each of us has our own understanding of these things what they mean i'm basically trying to say this just understand polymorphism understand good design don't worry about these solid principles because if you tell me that you have implemented the system using solid i'm not going to be impressed right because i don't i don't know what your understanding is i'm going to see it and everything i've seen so far including on youtube and other places there is something missing in that explanation or the example this is just way off base right it's just anywhere in the spectrum of way off base to not exactly what the intention is so then can i explain to you dependency injection without making uh without missing some of the stuff i mean i i'm gonna try [Music] it's i mean i i know i can explain it but whether you understand it or not will be yet to be determined that basically means i'm not sure i can explain it to everyone as in i don't have the capacity if you will to explain or make it make it understood by everyone but i'm hoping after this video you get a good idea of dependency inversion but also that essentially all of solid just boils down to proper design i'm gonna i'm gonna talk about that design aspect in this video that's really the focus of this point using dependency inversion as the kind of the guiding principle [Music] all right so i'm going to read the description of what uncle bob had published earlier right high level modules should not depend upon low level modules both should depend upon abstractions high level what is a high level what's the module what is the low level and what's the low level module right abstractions as you can imagine if you haven't seen my video previous video on app stations please take a look at here without that video i don't think i'm gonna get this this one okay so there'll be a bunch of videos you can watch uh as i talk about i remember them i'll kind of put the links up here but they're all almost prerequisites to this video and then of course in some cases the code that i might point you to also will be available through that video's link in the description right okay high level modules so we need to explain or understand high level we all have to be on the same page what the heck is a high level module right but conceptually let's understand if you had the notion of a high level module in the lower module i basically saying if something is more in control if something is let's say you're superior example your managers or your lead or whatever then that thing should not depend on you right but both you and the thing should depend on an abstraction that's what it's saying so if you have understood what a high level module is and let's say you are a low level module then the thing that is your manager or your lead that depends on you should not depend on you directly should depend on an abstraction and you should also depend on an app section but if you got the high-level module and low-level module wrong or if you weren't able to identify them to want to be a high level and want to be a lawyer they're both at the same level they're both you know to say siblings or peers there's nothing to help you determine right there's no way for you to know what is a high level what's the low level you could get it backwards you could not see it maybe you see them to be both players but there's one over the other right so there's a danger and under and not understanding or not being able to discern identify high level and low level okay and we'll take a little small example of that the second part here says abstractions should not depend upon details details should depend upon abstractions it seems like this sentence is a repetition of the previous sentence i'll let you see that again you may want to pause here so you in case you want to digest it before i move on i'm moving on now it seems almost that second sentence is a rehashing if you will stated the first sentence stated in a slightly different way where you know application should not depend on details but details should depend on what's nice it's almost like someone's trying to be really smart here right and this is some other issues i have with some of these things when i can appreciate that they do it and they can even dream these sentences up but that cleverness is becoming too vague or too abstract right and i mean if you want to have a phrase that these people should need should have some way to get to the kind of expanded meaning of that if the phrases is not going to get them to their expanded meaning then the phrase is kind of missing the point i find this a lot with you know design patterns as well you have to first understand the pattern before you can understand the kind of the the two-liner right but okay whatever it is what i found mainly is that most people think that the second point or sentence is the same as the first point rehashed it's not there are subtleties here that you need to understand and once you understand dependency inversion you will see that the second point or second sentence is not a rehashing of the first sentence you could see that way but you'll have a much deeper understanding of that so we'll spend some time looking at that as well in this video right all right so high level module low level module i'm starting from the place where this stuff came from uncle bob essentially says in his paper that you know from structured programming's point of view there's methods and method one calls a method two and method two calls of meth three and so on and generally if you've done structured programming correctly a method at a higher level of abstraction calls a method at a slightly lower level abstraction that calls potentially another method that's even lower and so on and so forth every time you call another method you're going one level lower in the form of abstraction meaning you're getting closer to the metal and you're getting closer and closer to doing kind of some real thing if you're nitty-gritty stuff of working with a file system or io or database or something but restructure programming the idea was you have a method call at a high level that probably did some orchestration some method called method one called you know a b e c d in some sort of a sequence then method a was slightly lower level level abstraction and then maybe method a call again other methods that were further lower and so on so in this case of the situation higher level modules was method one or method two as compared to method three but method one was higher or modulus compared to method two and so on it was fairly easy to understand that okay with objective programming let's look at this over here so you have a ui that depends on the domain layer that depends on the database or the data layer sorry which one is the high level module from a dependency point of view it seems like you know ui is at the high top and then there's the business layer or domain layer and then there's the data layer but you need to be able to identify which is the higher level module whether the module model could mean an entire subsystem an assembly a class a method it's a vague term but you can or should look at it as anything at any level you can play this game up which is the higher level module so this at this point we're looking at layers the ui layer the domain layer the data layer which is the higher level module right so the the way i see it is that the domain layer is my that i i protect the domain i'm building the system for me the system is the the stuff i protect everything else is ancillary right so the data accesses in many ways and sorry even though it's much much closer to the system as compared to the ui dui to me is just a implementation detail and i'll show you some other diagrams and you've heard me talk about this in other videos as well you know the day the layer architecture uh pattern and the implementation guidelines i'll put links to those two over here uh i forget the names exactly but one is talking about the basic layered architecture using the domain facade pattern and the other talks more about implementations the implementations part one is also more important because i'll bring some of that up here as well for me the ui is a lower level module even though it's drawn in this way it's actually a low level module so it's calling into the domain layer in other words the dependency this lower level module is calling into higher modules so for me this is fine i don't really care that there's a hard dependency if you will i could create some sort of a abstraction but i don't necessarily care for it because i could build any number of uis right by that i mean different technologies maybe i build a console application maybe i build a windows desktop application or a xamarin desktop application web application web api application it doesn't matter the domain layer is not changing right so which is what you want the domain the higher level module is not impacted by these lower level modules and if the lower modules change or you need new ones that's fine you just build a new one you're not impacting the domain player the domain layer doesn't need to know who all or what all things you are trying to use it right it is self-sufficient the domain there it is you know like a hard shell you can't break through this thing and it works completely by itself that to me is a domain there okay now for the most part the data layer is part of my domain layer but within that hard shell there is still like a separate boundary if you will it's almost like a house that has two rooms right there's the main big hall living room kitchen dining and then there's a bedroom so it's all in one home but there's a door between the main area of the house and this bedroom metaphor but nonetheless the domain layer conceptually is at a higher level than the data layer and what this statement is saying i'm going to switch back a couple pages here higher level modules should not depend upon lower level modules both should depend upon abstractions so you're inverting the dependency right it's also a bad name actually i don't believe that the name is correct so first of all what we need to see is this arrow instead of going from domain layer to data layer should go this way from data layer to domain layer and you're thinking like that's nonsense you can't have the data data layer called domain error correct so the dependency is not so much in terms of flow of control of call you know call chain it's dependency in terms of compiler dependency dependency in terms of what is the real referencing like references it's not so much to call the call is still going from the domain layer to the data layer in this case but who depends upon whom right so the flow of control is still going from domain of domain to business to data but we want to invert the dependency from from the perspective of compiler dependency from the perspective of references all right and to do that that's what we do we introduce the layer abstraction now i'm sort of using uml form here so that's showing me a composition there is some abstraction and this domain layer is compositing i was composed of that abstraction and this data layer is a descendant of this abstraction okay that abstraction could be implementing an interface it could be an abstract based class it doesn't really matter the idea is that the domain layer click that look at the diagram once again the domain layer depends upon at compile time it is referencing this let's call this a abstract class so you're just referencing this of course you will give it an instance of that descendant and it will use that but call that descendant directly as it is not the matter of calling who's calling home is more about who's dependent or from a referencing point of view or from a compilation point of view right so dependency inversion is all about inverting the dependencies from a compilation point of view and every time you use polymorphism like this that's what happens right you are in turn referencing an abstract class and not the descendants and so if you were talking to a concrete implementation introduce an abstraction and you got dependency inversion right get it simple so what's the big you know the blue part well i'm making this video for that so let me explain solid is a recipe is it not at least most people think it's a recipe so imagine you're making this you know your favorite dish you've got a bunch of friends and family over and you spend all day in the kitchen making this dish you you follow that recipe to the tea like everything has been meticulously followed every instruction followed exactly and now you sat down on the table you're serving everyone you know this dish and you have your first taste of it and it's it's not not anything like you expected even though you had this dish before right something is missing like salt salt can make your spices pop the if it's some sweetness the sweetness will pop the sourness soundness will pop everything pops with salt nothing without salt you can't taste pretty much anything it's like bland this ingredient salt is missing from everything we do with regards to solid and that ingredient is abstraction you see you don't get the magic simply by introducing a layer abstraction and inversion and wow magic happens this is the problem i have with things like solid it's like selling new snake oil you're not going to build a good system because you understand single responsibility or dependency in inversion principle or list of substitution principle any of these things the real missing ingredient i think is abstraction understanding abstraction now those who show you some examples you know in by blogs or articles they understand abstractions by the time they give you this interface right it's a good interface it's a good abstraction you don't know that they don't focus their their energies on why is that interface important why is why did i have to come up with this abstraction it's just magically they know the abstraction right and then they implement it saying oh you see how clean it is now but what about for those of us who don't understand abstraction or how to discern a good from a bad abstraction just because i inverted you know the dependencies here doesn't make me that i can make that system correct so the rest of this video is going to give you that extra ingredient that that salt your the ability to put salt into your designs to pop the taste the flavor give you the ability to understand how to descend good from bad abstractions okay just at a high level though but i'm going to show you that using code but before we move on let's look at the next slide here so i'm trying to show you a diagram which is typically a typical system that i would have i have a this blue dashed outline is my system okay that's the system this black box here is something i protect with my life what i'm building essentially is that that system and as compared to the previous diagram or slide here is comprised of the data layer and domain layer okay if there's a data lab and if the system needed data layer that's fine but if there's a data that's that's part of that thing but i'll explain why the front of this is a service interface layer which is even though we may build it i might build this that was invested it could be a web api or a ui abc ui or some other ui you know maybe a desktop application whatever it is i might be the one building up the team that i work with maybe we may be building it but it's not considered the system it is considered a slightly outside the system right now you need to look at that video i've put a link up here to the domain layer facade design pattern for something implementation guidelines i explained this thing i'll just go briefly explain that here but then i'm going to show some code these things are at different levels not layers but levels so let's say this is at level zero then these are level one these are level two level three and level four and so on and the basic idea is that a thing at one level can only talk to classes at one level down in other words this thing cannot talk to classes here these classes cannot talk to classes there and so on right so they can only talk one level down and i like to draw my systems like this something people will say do you what about onion application architecture what about uh ports and adapters architecture what about hexagonal architecture they're all the same this is the same as that those are the same as this i mean if you understand that and you understand this then it will all appear the same the difference really is that the way they're drawn and what is it what are they trying to show the importance that in my case i'm more interested in the flow i want to show you dependencies and flowing in one direction otherwise dependencies don't go backwards and forwards so if you can think of your system as a flow of dependency that a depends on b depends on c and so on and you lay out your classes physically in that structure it becomes easy to maintain the system ideas that sports and adapters are talking about the ideas that hexagonal marketing is talking about the idea is that i don't know whichever architecture they're all we're not talking about the same thing there is at some point at some point in time your system is either there's something coming into your system or you're leaving your system what do you call a system right and from once again you know what that system is when you leave your system you need to be careful about certain things when something is coming into your system you need to be careful about certain things i said i'll talk about that over here so for example configuration provider that is leaving your system it's potentially talking to a file system right or some configuration system if you were to build an abstraction here that may protect you for the future what that app station looks like we're going to talk about but think about that point you are leaving your system maybe not necessarily an abstraction so we'll talk about that but at least you might think that we may need an abstraction that if nothing else we may have to make sure we put some salt to pop the flavor all right but that's the class that because it's pretty leaving your system the gateway yes it's definitely leaving your system you need to be very careful about the the design if you will the abstraction not necessarily make an abstraction but design the methods correctly so basically the salt that i'm talking about is method design if irrespective of whether you pull out an abstraction respectively there's a base class or an interface it doesn't really matter right there's only one gateway class or the one config provider class it doesn't matter that there's no base class or there's no interface it makes no difference i'm trying to emphasize that point because if you followed the dependency inversion principle alone all by itself imagine there are a hundred classes in your system and class a well plus one since only 26 hours so class one depends on class two three four five six class two depends on then so on and so forth right the only class that doesn't have a dependency is class a so if you have a hundred classes that have some are participating this dependency graph you're going to have 99 abstractions do you really want to invert the dependency of every dependency [Music] of course not do you want 100 classes maybe 105 classes maybe 110 classes but you certainly don't want to have 199 things to manage right so n minus one basically if you've got an n class is n minus one this is my beef with people who implement solid and not justly implement even though people are big proponents of solid and they say you should be doing this every single place in your system i don't believe that i think that's the biggest the most incorrect advice anyone can give you you certainly do need to know or be aware of those seams or those boundaries you may not invert the dependency right off the bat and i'm gonna get about get to you about just because you invert the dependency it doesn't mean you've got it right right it's like you follow the entire recipe and yet that food is not tasting correct that missing ingredient is still missing i'm going to be focusing on how to get the missing ingredient in your designs so that if the time comes or even when the time comes and you want to invert the dependencies it will actually work that food will taste and all of all the flavors will pop because you now have the salt in your food all right all right so for now i just want you to sort of pay attention when you look at the system like this this thing you may not know what these things are but i've been actually just named these here the gate the validator is that going to leave your system probably not because it's probably doing something memory give it some data it's going to do some validation the domain facade itself not necessarily the emailer yes of course it's sending off an email so it's potentially leaving your system so maybe you want some you want to add the salt but not it abstract you want to add the salt but not yet invert the dependency and that's basically what i'm talking about here you need to recognize the areas of your system the seams or the boundaries or the i think the seams is one way to look at the boundaries the parameters of your system the things that leave your system and things that come and where things come into your system and how do you sort of decouple your how do you protect your system from these things where you're leaving your system or something is coming into your system and ports and adapters that's exactly what that is hexagonal architecture that's exactly what it is they're just drawing these systems differently okay they're they're trying to show you the and onion architecture same thing right the onion is saying you go from the outside in but it's not clear who can and should be or cannot be talking to others i'm more interested in that the dependency graph people that's what my concern is like if you look at the onion architecture or the hexagonal or the porcelain adapter there's nothing that says the ui can't talk to the detail layer but it's not obvious looking in the diagram what i'm saying here is the ui can only talk to the domain facade can only talk one level down it cannot talk it can't see for the most part because this is generally in an assembly and this is the only public class it can see it doesn't even know these classes exist so that's the that it may not be again i'm not going to go into details here but just understand that this can only things can only talk one level down and the reason i draw things this way is to show you that there's a certain idea of levels not layers but levels conceptual levels the way i've drawn these classes out and they are also at a level abstraction versus lower level abstraction so it all pans out class side level 0 for example this class here is at a much higher level abstraction than classes over here and classes and classes over here are at a much higher level of abstraction than classes over here and the classes over here are the lowest level abstraction in the entire system for the most part because they're doing some really kind of nitty-gritty stuff you know they're actually dealing with in this case database things right so they actually get down to the metal if you will so these classes here i mean from here to here there are a different level of attraction this is a higher abstraction this is at a much lower level abstraction this class may use some other classes that are even lower uh maybe you know http socket and things that we're not showing here but in the real system you have http client which is at a much lower level abstraction than the gateways and so on so the levels follow the flow of dependency and also you're i'm able to show you that you can only talk one level down so it's very clear okay but let's get back to the basic idea here so then i've got my data managers and as you can see the data manager talks to the database directly okay so if you remember the previous diagram with the business layerables and then there's a data layer and you have to invert the dependency right so you introduce this abstraction before we introduce that abstraction or even if we don't think we are going to do it today because that's not the point i'm going to show you how to discern a good abstraction in the first place because it's not just a matter of introducing an abstraction if you don't if your abstraction itself is incorrect if your public surface of this data access layer it's not correct building an abstraction and then building an interface or that has no purpose has no meaning you you don't you missed the point right so how do you discern what is a good abstraction so let's look at that let without trying to look at the class just look at these methods the signatures of these methods and also please just for now just ignore this core suffix so pretend that the core is not there right so for all these method names the core suffix is not there you're looking at the method signatures what the name is what are the inputs what is the output right what are the inputs what are the outputs look at this class and tell me what kind of a class do you think all these methods signatures here and tell me what kind of a class do you think that would be uh you can pause here and then related to the the slide i had here okay so this slide is it the one of these classes is one of these classes is one of these classes is one of these classes what do you think it is now may not make sense to you in case you the methods the names got you lost a bit let me explain that in that system imagine that system is like a tv station channel system and a channel has a tv channel has many shows and shows how many episodes and so on and so forth right so there's a channel that has many shows shows how many episodes and so on so the data or the sort of the methods you saw they were pertaining to some system that deals with channels and shows and episodes in this particular case the show's aspect was i think challenge shows was a pander what is that class signifying is it signifying something is it signifying the domain facade or the manager or these classes here or the data managers or these classes here and so on right okay so i'll tell you and it may not be obvious to you but i'm going to just tell you i'm trying to make a point here it's the data layer let's look at it you can see that this class is the show data manager that happens to be the base class but it's the show data manager as it shows and episodes shows or shows episodes and something it's a show data manager and it's a base class yes so it's an abstraction but that is irrelevant that is that's not the point i was showing this this could be implemented directly in the the data manager itself so let's let me pull up the data manager show data manager and let's look at one of the methods i'm just going to pull up okay simple that this so here's the method it's one of those methods we saw earlier that had the core suffix this is one of those methods get shows for channel course again you can kind of ignore the core sub suffix here get shows for channel given a channel id get to get me the collection of shows simple by looking at that method name and the signature you can't tell exactly where it's coming from like which class could be potentially implementing this method isn't it and that's the key so let's just try and discover that get shows for channel it seems to be a name that pertains to the domain in this case good shows for channel so which classes would have this name would your systems public service i mean let's say i'm trying to build a ui would you want my me somebody who's building a ui for your system you'll see a method that says get shows for channel see i would get like a list of shows or given a channel id yes you could say that that get shows for channel is probably a domain centric name ubiquitous languages they call it dddd a language that the business speaks in domain language not business in terms of just a business system whatever the domain is you know if it's a game it's in that language what are the inputs well in this case this is given a channel id i'll give you back a show a show is a domain model okay so we have a method here that says get shows for channel given a channel id get me back the collection of shows the show model this guy here is a domain model it is not decided by that input or the output as in the the caller called the ui or it's not decided by the database this show model is a domain model the business decides for me a show means these things if i look at the show itself here okay so it's got a bunch of things don't worry about it but basically this this is a just a plain old dtos nothing to do with something whatever like it's not descending from any other class it is just a class it's a domain model and in this case it's immutable so it cannot be changed once you create an instance of it either ways i'm hoping i'm sort of i'm going getting going slow but i'm hoping i'm making the point of people are getting knowing understanding people are you're understanding what i'm getting at yes this method happens to be for a data access layer the method name the method inputs the signature of the method is not giving it away right you can't tell there's nothing to do with the connection sql server sql statement stored nothing you don't know that it's not there okay as long as you agree let's move on let's look at the implementation though oh look at that this is a sql connection i got a connection it says you know command which is an sql command by the way okay for those who don't know ado.net and it says create command for and this is get shows for channels so it's got the same name get shows for channel create command for get shows oops didn't mean to go there right away get your shows per channel and then there's so let's look at what that does just to dig in here now get shows for channel is going to create an using a connection sql connection create a command and the command is talking to a stored procedure called get shows for channel the stored procedure name is also the same as this method name so basically this name because it's a domain-centric name it seems to be just flowing through the system isn't it the entry point the domain facade if you look at the diagram here the domain facade would have a name by the same method name by the same name similar signature meaning given a channel id give me back a collection of shows because that's a business thing this an aspect of the domain of this the system and then you go travel through the entire system you find that even the data manager here is talking to some command factory over there so far and deep into the cost of the system and this command factory is saying oh by the way i need to call a store procedure by the same name it's the ubiquitous language it's not going to change the name of the method is not going to change as you go deeper and deeper into the system because you're eventually trying to do the same thing what i'm getting at is that that abstraction is a clean abstraction it is not talking about implementation at all but how do you get that clean abstraction because you want to see this class helping you in the from from the perspective of what you are trying to do whatever you turn last time here's the class it's doing something for me whatever it is doing what is it doing for me i don't care what it is doing and how it needs to do and what it needs i don't need to know its dependencies and i certainly don't want to know how it works i know what it's doing for me though and i want to talk to this thing in my language the business language and by that i mean a few things the inputs and outputs are mine the method names are mine what it does internally i'm not concerned with and i don't want to know all right that is the second sentence go back here to the second sentence here abstractions so let's say i have this abstraction okay should not depend upon details meaning what the details in here are not surfacing through or coming through the abstraction abstraction does not talk about the first not dependent upon the details i don't surface an sql connection or a ef something model or what have you http client like you don't know that abstractions do not depend but depend it has many things they don't depend by theirs and they don't reference if you will the details and that's what it means the abstractions don't reference don't let the details leak through and therefore the details have to reference the abstraction i'm going to give an example of that too so you make it make sense to you what does that even mean okay so when we get back to the code but keep in mind the first part of the second sentence is abstraction should not depend upon details essentially if you have an abstraction here that you want to build to talk to something that's helpful to you your abstraction should be talking in your language your business language not in the language that it is working at it's working with a file system or a database connection or http socket whatever like the abstractions do not depend on the details which means the abstraction should not be referencing the details in any form of fashion because if you do that your abstractions are not clean so even though it's in the form of dependency inversion is essentially saying how to build a right abstraction all right okay move on to that and go back i'll leave it here so you can reference this thing again and switch to the code all right so here we have a store proc got that's got the same name as the main method we've been following along all the time if you look at the data manager here it had this method this is you know get shows for channel and then from that point four we also have them uh sorry let me go back here to the store proc it's also called the store boxes get shows for channel let's look at the uh it's been a while since i saw the database stuff here i'm going into my database looking for a storefront called get shows for channel this thing here all right get chose get shows for channel so the store blog is called get shows for this for channel it takes a channel id as an argument and oh my goodness see i don't want to know this stuff how many tables how many joins are there one two three four four or five joints stored procedures also provide you with an abstraction it's another layer of abstraction it's the stored procedure is saying you tell me what you need from a business point of view or you want to call get a channel cool i'll get your channel sorry shows for the channel sure i'll get you the shows for the channel how do you want it i want like that okay i'll do that i at the business at the application level don't want to know all the joins i'm not interested in those joints i don't care how the data model is structured you are free to change your data model any which way you like modify the stored procedure but i can still give it an id and still give me back the data that i want that stored precision procedure is giving me an abstraction if i had not built a design desktop procedure correctly a change in the data model will start to leak into my system and i don't want that that's a leaky abstraction you understand that procedure is giving me a separation and decoupling from the database the dbas can happily change their data model they can add you know 2000 more tables as long as that stored procedure can still give me the data in the form that i needed because my business has not changed because my abstractions are business centric i'm safer right of course if your business completely changes or your requirements totally change but this thing is no longer required or there's a big difference to know how you want and interpret that of course nothing's going to save you from that but this is more about decoupling from implementation details so if the abstraction is clean you are safeguarded against changes in this case at the store block level the abstraction is clean therefore if you if you change our database to add more data tables more joins will be required you can alias the fields in this case is calling these fields ide channel oh it says channel title c so it's aliasing them to be also the right type so what are these type names this is the field names the show type and title or show category and all that these are domain centric names whatever this is in the database doesn't matter the store processor's responsibility is to give you back the data in your language given it is its name is in your language it returns data in your language all right okay let's look back at the code now i'm going to close the store bro so i'm going back to the data thing over here so we got that connection we have the command factory let's look at this next part here it's got a data reader to model adapter i'll tell you what it's doing at a high level we're using data readers here that come that uh you know ad.net centric and the model is the the domain models the show so essentially what this thing is going to do is going to map or adapt a data reader to a model and it says create channel show sequence instance okay so essentially what it's doing is it's iterating over the records in a data reader and mapping them to a new show instance and then assembling a collection or a list of those show instances essentially the data is coming back exactly how we would like it one record at a time each record is representing a show how we got that data like this is none of this course business and this course is to the store product just give me the data like this i don't need to know how your database is right so the this code is also essentially saying the same thing i don't need to know how you do your stuff but i'm going to ask you for the store prop with the stand id give me back the data in this fashion in my language give me data back in my language okay there's a bit of a mapping required here which is what it's doing and it's mapping the data layer in this case is mapping the data reader to a show right so going back here given a channel id return to me a collection of shows going back to the signature now right let's say this is your database your data access layer there's no there's no base classes this is it right so imagine this is it but the signatures are this i'm going to go back to that base class you can see the signatures not just the one but all of these methods here so now focus your attention back on these methods ignore the core suffix just pretend this is some sort of an interface of an abstract based class or an abstract class or a class you've already implemented right this is the implementation these are all the method signatures right okay and let's say your current implementation is using sql server microsoft sql server and say you know you need to change this to using article can you do that good would that impact this this uh api here the public surface no okay cool so you don't need to abstract anything you could literally just throw away this this implementation the actual code and rewrite it to work with oracle that's what i'm asking for i'm not asking you to do the abstraction part and build an interface and all that if your abstraction to start with was correct if your method designs work correct to start with you could extract a base class from this but it implies that your original design method designs were correct only then then does dependency injection actually work correctly and so there's that assumption the fact that that salt was missing this is that salt your original design method design had to be in a good had to be good clean so that when you introduce an abstraction it actually works you actually get the benefit of dependency inversion it's not a silver bullet it's not going to happen just because you introduced an abstraction what i'm getting at is that method design is key and the way you design methods is by looking at from the perspective of the domain everything needs to talk the language of the domain at that point you because your domain is probably going to be the same then abstractions will remain the same if your abstractions are not built as for the domain then they will change so going back to this metaphor here going back to the same structure what if i came to you later and said hey guys i want to we need to use cosmos db azure blah blah and i use containers and it's an oco store can you implement the same class report all the implementation i'm not asking about having a base class in some hierarchy could you just rip out the implementation that is sql server centric and implement this whole thing with cosmos db things using the azure sdk and all that yeah you can because the requirements have not changed the details have changed implementation details have changed the abstraction has not the abstraction does not depend upon the details the details however depend upon the app session which means the details do have to map that data that came from using a data reader to a show model domain model the details do depend upon the abstraction but the abstractions don't depend on the details make sense all right i could give you ton of examples of this i don't want to bore anyone i think this video has gone on quite a bit i hope you found this interesting if you do want me to go into more details i'll be happy to do that uh oh i'll also put a link to my adapter design pattern video that talks about the publishers and the adapter i'm using dependency inversion but talking about the adapter design pattern because dependency inversion is nothing but polymorphism and and most patterns are also polymorphism so if you want to see another example of dependency inversion please take a look at that video on the adapter design pattern all right so yes i've been complaining about everyone else's ability to explain dependency inversion how would i do did you get it finally do you like this explanation if you did and if you've learned a few things please give me a thumbs up and i'll see you next time
Info
Channel: Shiv Kumar
Views: 2,460
Rating: undefined out of 5
Keywords: SOLID, Single Responsiblity Principle, SRP, Open Close Principle, OCP, Liskov Substitution Principle, LSP, Interface Segregation Principle, ISP, Dependency Inversion Priciple, DIP, Polymorphism, Abstraction, Software Abstraction, Software Design, Object Oriented Design, C#, .NET, .NET Core, Weak Abstraction, Strong Abstraction, Decouple, Decoupling, Software Decoupling
Id: IZ_7K7XOABM
Channel Id: undefined
Length: 55min 2sec (3302 seconds)
Published: Sun Feb 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.