Robert C Martin Clean Design, Components Principles

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
up in there in the back you hear me okay yeah good okay so what's the speed of light three times 10 to the 8th meters per second thank you that's correct how do we know this Einstein Einstein definitely had a lot to do with the speed of light but we knew the speed of light long before Einstein how do we find out what the speed of light was first gotta measure it or try to measure it was Galileo Galileo curious about the speed of light climbed a mountain with a lantern with a a rag draped over that lantern and he told his servant to climb another mountain with a lantern with a rag over his Lantern and he told his servant when you see me uncover my lantern you uncover yours and I will time it with my pulse his conclusion was that the speed of light was damn fast we didn't have a really good grasp of the speed of light until all the 1600s when we had managed to discover the size of the solar system once we knew the size of the solar system then we could time the orbits of Jupiter's moons and the earth would be in a position around the Sun in January and then in June six months later the orbiting of the moons would appear to be sixteen minutes delayed because it took 16 minutes for the light from Jupiter to cross the Earth's orbit so and we knew the size of the Earth's orbit 186 million miles and so we knew that light moved at about 3 times 10 to the 8th meters per second this got better and better just refined there were a whole bunch of ways to measure it after that nowadays we measure it electronically it was measured some time ago with a spinning mirror and if somebody would take a mirror and spin it real fast and reflect the light off 20 miles to a mountain where they'd set up another mirror and it would come back and it would hit the same spinning mirror but the mirror will have shifted just a little bit which would have deflected the angle a tiny bit and you could measure the deflection and calculate the speed of so we've known what the speed of light is for years around 1830 something this fella I don't even remember his name did a strange mathematical experiment he took the charge the unit of charge Q the unit of charge and he divided it by the unit of magnetic flux now why he wanted to do that I don't know but you know one of them was Faraday's theory of electricity and one of them came from Gauss's theory of magnetism and he just did the unit analysis dividing the two units and an interesting thing happened when you do all the divisions you wind up with a velocity and that velocity is three times ten to the eighth meters per second now the guy who did this division knew this he knew what that was it was the speed of light but he had no idea why the ratio of the electric charge to the magnetic charge was the speed of light you can imagine the chills going down this guy's back there's some deep hidden mystery here he never really figured out what it was it took Maxwell to figure out what it was Maxwell's the guy who said well yes the reason for that is because the electricity and our electric charge and magnetic flux are actually the same thing at Maxwell did the first Unified Field good and he proved that an electric field when it oscillates creates a magnetic field which creates an electric field which creates a magnetic field and that this oscillating oscillating dance of fields will propagate at the speed of light and when he did his formulas the speed of light just drops out in meters per second and then Maxwell asked this wonderful question what's the frame of reference what frame of reference is there for this velocity why is it that a velocity drops out but no frame of reference for the velocity there's no such thing as an absolute velocity you know you it may look like I'm walking at 3 feet per second but you know the earth is turning at a thousand miles an hour and the earth is rotating around the Sun at 10,000 miles an hour and the Sun is moving around the galaxy at 50,000 miles are and there is no such thing as an absolute velocity and yet Maxwell's equations pop out with an absolute velocity and you didn't know the answer to it that's where Einstein comes in thank you for that now we're going to talk about component principles today's talk and I have you I think for about an hour is the follow-on to the last talk I gave you the last talk was about solid principles or principles that govern the relationships between classes this talk is about larger scale issues and the the relationships that govern there are the principles that govern the relationships between components large assemblies of classes I begin this talk with a scare tactic I'm going to scare you about the future of our industry this is a graph of my personal history in software showing the size of the systems that I worked with in each decade up to the 2000s right and in the 1960s I was a very young software developer and the size of the applications I was working with was on the order of a thousand lines of code 2,000 lines of code is a big program it was a full box of cards ten ten thousand lines that was five boxes of cards it had serious weight you couldn't carry it down the hall but he had to have a hand truck to wheel it down the hall take a long time to feed it into the card reader so you practical for practical reasons it was difficult to get large programs in the 70s I was working on many computers and we are our storage medium was tape drives nine track tapes no less that all went in one direction you couldn't rewind them so these tapes were in an endless loop and you would you would record your data on them and you'd keep on recording and kill you forward spaced it back to the beginning of the tape we would we got old say 50,000 lines of assembly language on those those kinds of tapes and that was the size of our applications about 50,000 lines of us language by the 80s I was working on a on the same system actually same company same system but we had grown and grown it can grown it to the point root is about three hundred thousand lines of C code by the 90s I had become a become a consultant and traveling around the world and helping people get their software done and the kinds of system I systems I was consulting on were in the millions of lines of code and now it's the 21st century and the kinds of systems that I consult on and see with my clients are in the tens of millions of lines of code and I think you can see a pattern here every decade seems to see an order of magnitude a power of 10 increase in the size of the systems that I see now I believe that that's related to the industry as a whole I think that a thousand to two thousand lines really was the mean in the 60s and that t/o tens of thousands of lines really was the mean in the 70s and that this progression is really the case how many of you are working on a program that is more than a million lines of code and if that would have been a lot of you are that would have been impossible ten years ago maybe one of you would have snuck your hand in the air now a million lines of code well yeah lots of people do a million lines of code that's nothing it's it's the ten million line ones that are interesting how big is Windows we have which one yeah but that's what NT and T was thirty five million lines of code what the heck is Vista and never mind about Vista how big is seven how many lines of code in there could it be close to a hundred billion lines now anybody know and ten years from now well we have Windows 8 will it be a billion lines of code how do you deal with a billion lines of code well we may not have to worry about that because there's another effect this was a study done 1994 it showed the probability that a project would fail as a function of its complexity and you can see that's a fairly frightening curve you know the more complex the function is the more likely it is to fail so there is a conclusion we can draw from that it may be that there is a maximum complexity beyond which 100% of all systems fail there may be a limit to how big our systems can be and if that's the case it does not bode well for our civilization because we need the ability to deal with more and more complex programs so we need some mechanism to help us reduce the complexity so that we can have larger and larger systems coupling one of the things that increases the complexity of systems is coupling and you can see the problem right here you see Dean pop up there for a minute yeah okay you can see the problem right here here is a maje or a system which contains seven modules how many couplings exist in that system well it could be high as 49 and 7 squared it's the number of diagonals of the polygon but couplings are worse because they're directional right so you have to count the coupling from here to here and the coupling from here to here so it's possible you can get 49 couplings in a system of 10 modules if you have a system of 100 modules it's possible to get 10,000 couplings N squared do you ever actually get that well yeah actually you do but through devious means which I will describe the number of couplings increases with the square this curve we will see again that's just an N squared curve but we will see it again in more frightening terms that's just the same picture elaborated more now I'm going to take that picture and I'm going to turn it around I'm going to switch it around and say what is our productivity if couplings increase we know that coupling slowed us down we know the more couplings there are the slower we go who here has been significantly impeded by a messy massive code okay so you know that the messy mass of coupled code slows you down here's the curve how many of you have worked on a project you started out and everybody's going like lightning yeah oh we can code our way to heaven with this thing we can code features come in and we get them done in no time lightning crackles from our fingertips because we're so good at coding and then a year later ah I've got this ball and chain or on my leg it's like walking through molasses I can't get anything done every time I touch the code 80 things break we wind up going down this productivity curve sliding down this curve so that a year later or two years later it takes forever to get anything done what does management do about this management remembers what it was like to be up here they got lots of stuff in the early days who was great they thought they were gonna make a load of money and then a year later they can't get a damn thing done what do they do about this what can they do what knobs can they turn to make you go faster hire more programmers that's the number one thing all right well we just need more people now we're gonna make more people which will raise the productivity slightly except there's a problem the new people don't understand the design so they make a mess faster than the old guys do driving this right back down so a month later the managers are going oh I didn't work let's hire more and you wind up with this interesting saltiest curve as the staff increases and the productivity does not whole companies go under because of this effect what can we do about it yes yes yes thing take a look at this this is the structure of a system with seven modules and the number of couplings are one two three four five six six unidirectional couplings that is the minimum number of couplings you can have in a system of seven modules this is the maximum number of couplings 49 one of them is less than n one of them is N squared and can we give our systems to look like this which of these two would you rather maintain it seems pretty clear so we would like of course to have our systems look like this but there's an ugly secret the ugly secret is that a system that looks like this or almost like this can in reality hidden behind the scenes look like that no one can see that it looks like that but it does and I'll show you how that happens some poor schmuck working in module number six sees a function he wants to call in module number one and he does the worst thing he could possibly do he calls it that creates a dependency from six to one now you may think okay we've added another dependency no we have not added another dependency because now module six depends on module two so six depends on two and six depends on four and six depends on five and six depends on three and six depends on seven we have multiplied the number of dependencies by seven it's actually worse than that because three depends on six which depends on one which depends on to it trends on four and five so three depends upon all of those we have multiplied the number of dependencies by fourteen that one dumb read dependency because it created a cycle in the dependency graph created 14 transitive dependencies out of thin air and we can't even see them when we look at this but they're there and when you make a change here it can now break that that didn't used to be possible but now it is possible now there's a way to make a change here to break that or to make a change here and break that that is now possible to do simply because of one stupid dependency that one stupid programmer did when he called one stupid program how many of you tracked the cycles in your dependency graph not nearly enough of you this is a an actually a fairly significant issue in the structure of your systems and we're going to talk about it shortly but first we're going to talk about components and what they are no stop with that stupid animation here is the productivity graph of more and more and more modules that follow this structure a nice tree structure the productivity graph barely goes down at all whereas here is the productivity graph if our modules create a cycle if there's a cycle in the dependency graph anybody been a C++ programmer good anybody remember the day when the compile took too long right then it happened like all of a sudden you're working along and you've got maybe a hundred thousand lines of code and you can compile it in a couple of minutes but a month later it's taking an hour to compile why because you've crossed the knee of the curve and as you add more and more modules the compile time goes up with the square of the numbers of lines of code you can do the math on this if you want it's a fairly simple math this curve here can be a curve of the build productivity but worse it's a graph of the team productivity we are going to talk about several principles the first three are principles about what goes into a component these are the principles of component cohesion the three principles that govern what go in components and then we are going to talk about three principles of component coupling the three principles that govern how how components were are related to each other what the heck is a component a component is a binary module it's not a not a batch of source code it is a binary module it's an executable module and it is independently deployable so in the.net space this would be a DLL and assembly in the Java world it's a jar file in the C++ world it's a shared library or an executable whatever it is it is independent independently deployable and it's binary you may have package statements or namespace statements in your source code they are not components they do not define components those are just scoping mechanisms although it is to your benefit to make your namespaces or packages correspond at the highest level to the real components we draw these in this class I'm going to draw them as simple UML diagrams a component is a big box with these funny little rectangles on the side that's a component and it will consist of classes so a component always has classes inside it this would be a control panel component just so that you know what my diagrams will look like and this is a diagram of a system of components and the dependencies between those components follow the arrows and there are no hidden dependencies anywhere in here all right this shows you how the components relate so that's the kind of diagrams we're going to be looking at now the first three principles what should you put into a component what are the classes that belong into a component into a component and the first principle is the release reuse equivalency principle imagine that I have a component and I want you to use it I have all the source code for it and I will maintain it I will make regular releases of it and give you the binary I'll give you all the documentation I will show you all the tests what else do you want what do you want me to do so that you will use my component what's that interface yes I will have an interface to the compound to the component you will not have to depend upon any concrete classes I will have nice polymorphic interfaces at the front of the component that you can depend upon what else all right sorry liability stability what what what do you mean stability you don't want me to change it well I got to change it you know I'm gonna be releasing it I might have to change the interface I'm gonna be changing it every couple of months I've got to make new releases and when I do well you're just gonna have to live with that you might not like that last little bit you might not like depending on the vagaries of what I am going to do but I can make you this guarantee every time I change it I will put a new version number on it and I will grandfather the old version for a couple of months I will support the old version for a couple of months you can take the new version and experiment with it and if you decide that you can still use it or you can change your code to use it with the changes I've made then fine you can continue to use it otherwise you can take the source code and fork it and you can maintain it yourself you can turn it into your own component I can make you that guarantee in order to do that I must institute a process whereby I release the component I stamp it with release numbers I warn you in advance of the changes that are coming and I give you time to incorporate those changes and evaluate them and if I'm not willing to do that you are not going to use my component so the first rule of creating components is you've got to have a release process you've got to stamp it with release numbers and you have to have a way for other people to feel secure that they can use your component this has been one of the big barriers to reuse we can't reuse something if we don't understand how it's going to change it also puts an interesting constraint on what goes into a component because now we have to look at a component as something that we can gather together and release with a certain kind of rhythm every couple of months we're going to make a release and we're going to notify all of our users we better keep track of who all our users are so that we can send the appropriate emails and we better keep the documentation up-to-date so that they can look at the documentation and know what has changed that is the minimum necessary in order to get other people to use a component so the granule of reuse is the granule of release the smallest thing that anyone else is willing to reuse is the smallest thing that you are willing to release with some kind of standard process that's the first principle the release reused equivalency principle the second principle is called common closure and if you were in my previous lecture you will remember that I talked about the single responsibility principle the single responsibility principle said that a class should not change for different reasons now I'm going to promote that principle to the component level and say that a component should not change for different reasons in fact what I want to do with a component is gather together into that component all the classes that change for the same reasons and push out of that component classes that change for different reasons let me ask you this question a feature is coming I know about this feature I've been warned about it I have designed my system to be flexible so that when this feature occurs the minimum amount of change will be necessary when the feature arrives and I must implement it how many components ought to change one that's the best possible case one when a new feature arrives if you can change a single component you have tuned your component structure perfectly now most people can't do that it's not easy to tune it to one but if we can minimize it minimize the number of components to change the worst-possible-case is when you change a feature or add a new feature and every component in the system changes that's bad so this principle says figure out how classes change and group together the classes that change for same reasons put them into components separate classes that change for different reasons in the example we used in the previous lecture we would like all of the classes that deal with the database to be in one component we would like all of the classes that deal with business rules to be in another component we would like all of the classes that deal with report formats to be in another component so that they all change for the same reason and they don't change for different reasons these two principals fight each other they don't exist well they don't coexist well because this one says well group together as much as you can and release it and this one says separate as much as you can by change so it is not easy to get these two feet these two principles to work well together and in fact what we will find is that while we are developing we tend to be over here more and when we have lots of users we tend to be over here more which means the component structure of our system is going to change over time the components the components structure that is conducive to development is not the component structure that is conducive to reuse there will come a moment while we are developing that we will want other people to start using our components and when that occurs we will have to make a change to our component structure to move it in this direction but there is yet one more principle involved it's called the common reuse principle and it works like this I think I've got my picture right here I have a component and you have a component and your component depends upon mine but your component does not depend upon everything in mine it only depends upon one little part of my component this is the problem now if I make a change to that part of my component it shouldn't really affect you but it does it does because I must redeploy this entire component the version number is going to have to change and that means you will have to redeploy your component even though nothing in it that you care about has changed who did not move to vista why not something nothing in it changed that you cared about and there was a lot in it too changed that you didn't want to have to deal with right so you stayed with what XP how old is XP ya good 9 years of the decade is it a decade no that's good 9 years old didn't even bother go to Vista nothing in it changed that I care about I remember the day when I changed from Windows 98 to Windows 2000 I'd had the CD on my desk for a good long time so the year was probably 2002 and it was like midnight one night and I I was just sitting there and didn't feel like going to bed my whole family had gone to sleep and I thought oh what the hell I'll stick the CD in my drive and upgrade my laptop up on the screen comes this wonderful billboard some of you might remember this congratulations you are now upgrading to Windows 2000 and then there was this nice billboard metaphor as the billboards would move by on looked like I was driving down the street and new signs would come up saying only 45 more minutes until you can use Windows 2000 and I would be reading my book and doing whatever look up everyone's going Oh 15 minutes left good good good and then finally after 45 minutes of this a billboard popped up saying congratulations Windows 2000 is about to begin will now restart your computer crash so now it's 1:00 in the morning and I'm thinking ah my laptop's not working now there's no way a serious geek can sleep if his laptops not working you cannot go to bed right you've got to get it working again so ah alright what am I gonna do here to try and reboot it and Frank and unfortunately this was in the days when a reboot took 15 minutes remember those days so I've rebooted a couple of times couldn't get it to reboot so then I went into safe mode safe mode where every pixel is the size of a postage stamp right then you just trying to scroll around the screen so that you could go into the control panel and bring up the system drivers and turn off the drivers one I won of course you don't actually do that you do a binary search on the drivers so you turn off half the drivers and do a reboot oh it rebooted okay um I'm gonna reboot again and turn off just a quarter of the drivers who that failed okay and then you're just kind of isolate him after several hours I found that the system was crashing because of the speech synthesizer driver on the modem chip I didn't need that so I turned it off and everything was fine after that but it was a hellish procedure that was this problem something changed that I didn't care about but still it impacted me we don't want to have that happening in our system so when we see this one user using only part of our component we want to split the component at that point and create two components out of it so that we isolate this guy against changes in those guys that he doesn't care about that's the common reuse principle and it creates yet another dimension in this force triangle that that the principles fighting each other in if you look at this dynamic triangle here these are the principles at the corners these lines here represent the bad effect of not implementing that so if you don't implement this the common reuse principle you will receive unneeded releases if you don't implement the release reuse equivalency principle you will get too little reuse convenience and if you don't use the common closure principle changes will split amongst the components you'll have lots of components to change instead of just a few this is the set of trade-offs that we have to live within when we're designing our component structure and early in our life early in our development lifetime we will want to live over here so that it's easy to develop and later on we're going to move over here so that it's easy for other people to reuse the final lesson of these three principles is that your component structure is not static it's dynamic and it depends on your audience if your audience is developers you're going to structure your components over here and if your audience is other people and other groups that want to reuse your stuff you will restructure your components to follow those principles over there having made the decisions and remade and remade and remade the decisions about what will go into our components what should the relationships between the components be the relationships between the components are governed by three principles the first called the a cyclic dependencies principle the next to the stable dependencies principle and the third the stable abstraction principle the a cyclic dependencies principle you go to work say two o'clock in the morning or 9 o'clock wherever you go to work and you begin to do your coding you're cutting away you're getting your tests to pass you're adding more code you're getting your tests to pass five o'clock it's time to go home all your tests are passing you go home feeling pretty good you come in the next morning and all your tests are broken what happened somebody stayed later than you and checked code in on top of yours and broke it maybe they live in a different country so now you have to work all day to get your stuff to work again you go home you come back the next day and it's all broken again how many times can you go around that loop right this is a common problem of large teams when you have large teams we tend to step on each other this is an old old problem it's been around for decades and there are two fundamental solutions to it both of these solutions were invented by the telephone companies because they're the first ones who had the problem and the first solution is the weekly build we're going to allow all our programmers to ignore each other for four days they'll all check out the code into their own little sand boxes they'll all make whatever changes they want to make and run all our tests for four days and then on Friday we will all get together and we'll integrate this is the weekly build and it works just until we get to the point where integration starts to take a little bit longer than Friday as the system gets more and more complicated taking longer and longer to integrate and so then we've come in on a couple of Saturdays we don't like that somebody gets the bright idea that we should start integrating on Thursday afternoon and now we have set the line of integration into motion that line will continue to move it'll move to Thursday morning and then it'll move to Wednesday afternoon or the wind it moved to Wednesday at noon and about when it gets to Wednesday at noon and our duty cycle is now 50% someone will get the bright idea that oh you know what we should do a biweekly build build once every two weeks that'll give us a week and a half of development and a half a week of of integration but the line of integration continues to move until it gets to a late Friday of the first week and someone says oh this is awful we're integrating just as much as we're developing let's integrate once every month I worked for a telecommunications company I consulted for a telecommunications company in Canada which had gotten to the point where they were having a monthly integration cycle and it was so painful for them that they decided that they were going to stop developing and for three months they would break the dependencies in their component structure and reorganize their software so that they could use the second traditional approach the second traditional approach is very simple organize your components so that there are no cycles in the graph now here's one that has a cycle right that's a cycle in the dependency graph organize your components so that there are no cycles if you do that see if I've got a nice picture here we go if you do that if your components have no cycles then you can play the following game the guy is working on the alarm component that's a team the alarm team and there's the conveyor team and the elevator team these guys are all working on their components the alarm guys managed to finish a release first there are one dot release which they put in a directory called alarm1 dot oh and they sent an email to everybody else saying hey alarm1 dot o is ready everybody can use it the alarm team then starts to work on one dot one meanwhile conveyor and elevator are happy because they just got the release of alarm one dot oh they can start calling it now they start calling it they're starting to release their one dot over jhin's which another week later they will do and when they release their versions up put them in special directories and they will send email up the stream so that the transport guys can call them meanwhile alarm is working on 1.2 count of elevators working on 1.1 transports working on 1.0 and this whole wave of development propagates up the tree and it's very nice because you're never you're never dealing with something that's changing these guys working on their 1.1 are depending on alarm 1.0 these guys are making the 1.1 changes in a completely different place so you don't have the fight this only works however if there are no cycles now along comes one guy one poor schmuck and he does that poor guy he's working in the alarm component and somebody tells him he's got to print a message on the console and he goes up here he sees a function oh yeah there's a print on the console and he calls it and now there's a cycle in the dependency graph perfectly innocent thing to do all he did was call a function but now conveyor would like to do their 1.3 release in order to do their 1.3 release they need alarm 1.3 but alarm 1.3 needs control panel 1.3 which needs transport 1.3 which needs conveyor 1.3 which is the one we're trying to release so all this code is now checked out into one place and everybody's modifying at the same time and they're all stumbling all over each other breaking each other's code as soon as that cycle goes in you have to check it all out together there's no way to check it out independently part of being able to independently deploy is to be able to independently develop even if you know bird independently deploy your components you still want to be able to independently develop them but the problem is actually much worse than that the elevator guys are ready to run their unit tests but they find that when they want to run their unit tests they need to include alarm that doesn't disturb them so much but alarm wants control panel which wants revenue which wants the database the database has been broken for six months nobody understands why and it takes 45 minutes to just load the doggone thing these guys can't run their unit tests and they're pretty upset about it and they find out eventually the reason they can't run their test is because some poor guy down here made that relationship and they find him and they take him up back and they beat the crap out of them I was that guy by the way this is how I learned that lesson right don't do this now how do you deal with this well it's real easy to deal with this you you get a two older if there's dozens of these tools out there you can find them all over the place that will tell you if you've got any cycles in the graph the visual studio almost does this for you cuz it won't let you have cycles in some parts of the system you probably want a little bit better than that but you can get a tool like independer or something like that or if you're in java jada pen or any of the other dependency trackers and you can find these backwards relationships and then you break them by the employing the dependency inversion principle what's really going on here is some class in here is depending on some class in here well we know we can take any dependency between two classes and turn it around by sticking an interface in between them so probably what we're going to do is use a dependency inversion approach or pull that whole function out into its own component take the display out of the control panel just rip it out and call it from both alarm and from control panel either of those two approaches will work it's trivial to do as long as you don't let it get away from you so as soon as a cycle is detected you rip a new component out or you put an interface in and turn a dependency around one of the two and you wind up with nice a cyclic structures that you can develop independently this is the dependency inversion approach here where the control panel now depends on some interface and the alarm implements that interface of the control panel and the display work differently the stable dependencies principle what would you rather depend upon a component that's stable or a component that's in stable it's a trick question right of course the answer is you want to depend on something stable so I will ask you this question is that stable it's not falling but yeah I wouldn't actually call it stable Cripe it's chaotic it's not changing it's not falling over but I wouldn't call it stable it is not good enough that a component not change to call it stable it has to be hard to change right it's going to be hard for me to knock this table over well not that hard if it were a well-designed table it would be hard for me to knock it over it would be hard for me to knock this concrete thing over it's very stable why is it stable it's hard to change but that pen easy to change it just didn't happen to be changing at the time but it's easy to change so let me rephrase the question what do you want to depend upon something that is stable hard to change or something that is not stable easy to change which would you rather depend upon now same answer hard to change you want to depend upon things that are hard to change think of how good you feel about depending upon the string class it's impossible to change right guys who change that would have to pay a terrible penalty to change the string class right so you feel perfectly good about the fact that they will pay much more than you will have to pay it'll hurt them a lot more than it'll hurt you and that's exactly the equation you want to have in your head you want to depend upon things that are hard to change because then they aren't going to change and they will have very little impact upon you what is it that makes a component hard to change dependencies the number of incoming dependencies to a component the number of other components that depend upon it make that component hard to change we could look at a number of dependency graphs like this one yes we've got a component here and a number of other components depend upon it this component is responsible to all of these it it if it changes all of those are impacted we call this kind of a component and adult because it is responsible to all of those guys and it has nobody it depends upon it's responsible and it's independent it is an adult then there's this kind of component this kind of component depends upon many others but nobody depends upon it it is irresponsible no one depends upon it and it is dependent because it depends upon many others irresponsible and dependent it is a teenager we will have components of both kinds in our systems some of our components will be heavily dependent upon they will be stable stable adults and some of our components will depend heavily on others they will be in stable teenagers that variable changing their minds all the time we can actually measure this we can put a number on it we can say okay this component right here has three incoming dependencies and it's got one outgoing dependency the incoming dependencies we could call CA for afferent couplings the outgoing dependencies we could call ce4 in our outgoing dependencies and we can come up with this interesting number I I is called instability instability is a metric that goes from 0 to 1 if I is zero what does it mean that C a and C er seee is zero the incoming dependencies are zero or the outgoing dependency is zero and the incoming dependencies are not right so there are many incoming dependencies but no outgoing dependencies that's the adult what if I is a 1 then CA is 0 there are no incoming dependencies but there are outgoing dependencies that is the teenager so an eye of 1 is a teenager it's unstable unstable an eye of zero is an adult it is stable and we can we can do this math for all of our components and then we have a very simple rule the state the stable dependencies principle says depend on the or in the order of decreasing I every component that depends on another component should depend upon one that has a lower I metric than it does why nope I need the need to picture again imagine imagine a component named easy I call it easy because I want it to be easy to change do we do we create components that we would like to be easy to change of course we do you know we want to put all of our language files in components that are easy to change we want to put all of our configuration data into components that are easy to change we want to take all of the code that is variable and put it in components that are easy to change and that means they need to be in teenagers components that depend outwards but have no incoming dependencies so we want to create components that are easy to change but there's another component out here H H is hard to change why is it hard to change because it has many incoming dependencies and now the author of H mentions my name he hangs a dependency on me and what has he done to me if H is hard to change and H mentions my name and then and therefore depends upon me what has he done to me he's made me hard to change it is the perversity of software that someone else can make you hard to change by mentioning your name I alway have to do is hang in dependency on you and they ruin your maintenance characteristics so we've got this H thing with an eye metric of zero depending on an easy thing with an eye metric of one that's the wrong direction what we want to do instead is without a new component whatever it is that H wanted to depend upon we need to pull out an interface so that H can depend on an interface and ez can implement the interface they'll both depend on the interface nobody will depend upon easy and make easy hard to change that's using again the dependency inversion principle to keep these metrics in line and that leaves us with one principle left now we have component structures where the dependencies between the components flow towards increasing stability decreasing I they get more and more stable as you go down the network but imagine following the dependencies from the top of the component structure to the bottom at the bottom of the component structure you have the maximum stability they are very hard to change down there and that should bother us because we don't want to have components that are hard to change and yet here they are there's a million dependencies funneling down resting on those bottom components but there's an escape clause the escape clause I told you about last hour was the open closed principle the open closed principle said ok these guys down here might be hard to modify but you can extend them can you make them extensible by using the open closed principle these components down here that are very difficult to modify because everybody depends upon maybe we can keep their flexibility going by making them extensible and how do we do that how do you make something extensible even though you don't want to modify it abstraction so the last rule the final principle is simple the further down you go in that component graph the higher the stability of the component the more abstract the component needs to be at the top you've got con creet components that nobody depends upon at the bottom you've got abstract components that everybody depends upon and that's the perfect balance the stable abstraction principle says we're going to come up with a new metric that metric is going to be a a is simply the number of abstract classes in a component divided by the number of classes it is a metric that goes from 0 to 1 if the metric is 0 you've got a completely concrete pack a concrete component if the number is 1 if a is a 1 you have a totally abstract component and now we can take these two metrics a and I and we can plot them against each other and we can say here are the ideal places for a component to live a component can live here very abstract and everybody depends upon it within an eye of zero everybody depends upon it or and a component can be totally concrete and nobody depends upon perfect those are the two perfect cases the adults and the teenagers unfortunately components are never perfect there's always middle cases there are going to be components that are neither here nor here but somewhere in the middle and where should they be so we're gonna take a look at this graph and they say well what about a component that's out here a component out here is very abstract and no one uses it no one depends upon it an abstract class that nobody derives from what would you call that useless this is the zone of uselessness we don't want our components moving in that direction the more they go in that direction the less useful they become so we'd like to see our components moving away from that part of the graph what about this part of the graph what is a component that lives here and it's very concrete and everybody depends upon it this is a database schema concrete everybody depends upon it fun to change right this is the zone of pain and we don't want our components living down here now I need to say something about this there are certain classes which are concrete and heavily dependent upon and it doesn't bother us like stream string or vector or any number of the library classes which are perfectly concrete everybody depends upon them doesn't bother us why doesn't it bother us because they don't change if they're not going to change nothing here bothers us there's another access to this graph that comes out of the screen points at you it is the axis of volatility and what we are looking at here is a slice of that cubicle graph where volatility equals 1 these are the things that we are actively developing right now they are volatile because we're working on them and because we're working on them we don't want to depend upon anything that is highly concrete that was the dependency inversion principle you may remember from last hour depend on things that are abstract so this is the zone of pain if volatility is high and therefore we would like our components to live either here or here or somewhere on this line as far away as possible from the two end points so we can come up with one last metric that metric is the metric D D is the distance of a component from that line and it's a very simple metric to compute you take a plus I subtract one and do the absolute value and you get D D is a metric that goes from zero to one zero means on the line that one means as far away from the line as possible and if you want to know in which direction it's away from the line take the absolute value away but I don't I just forget about the absolute value leave it in there I don't care where it is on each side of the line I just want to know how far away it is from the line and with that I can now come up with a set of metrics I can measure my components and see how close they are to this balance between abstractness and incoming dependencies if they are very abstract with lots of incoming dependencies good if they are very concrete with no incoming dependencies good if they come out here they're abstract and nobody uses them they're useless if they come in here there highly concrete and lots of people depend upon them they are painful there's a bunch of metric tools that will calculate these metrics for you and depend will calculate them in c-sharp and I think in VB and I think the the the resharper plug-in has some of these metrics as well and you can get a whole bunch of other tools out there and if you go out there and take a look that will calculate these metrics for you or if you want to you can write a little script that calculates on yourself it's not that hard to do and that's the end of my presentation are there any questions in the last few minutes there now I can see you know questions yeah should should you package by features or should you package by layers so I wouldn't package by either of those features features tend to use lots of different parts of the system so if we were to draw a component diagram of our system and then show which components are touched by features we would very likely see a thread attaching several several components together to make a single feature work so I don't want a component pour a feature what about layers well layers are things like GUI middleware database do I want to take each one of those and make them a component no probably not because there are things in the middleware that don't change for the same reason so I'm probably gonna want to separate the things that change for different reasons there are things in the GUI that change for different reasons certain screens will change for one reason certain screens for another reason certain widgets will change for one reason and another reason so I probably want to separate them again so there's very likely no relationship between the component structure and the level structure and the features certain components will be in the GUI layer certain components will be in the middleware layer certain components will be in the database layer and as you thread the features through you'll find that the features dive through the layers through certain components did that make sense wasn't good news though but anybody else yes I don't know what the dot and that extensibility methods are extension methods what is that what meth muck there is a design pattern called extension method but I don't know if that's what we're talking about oh is this the ability to open up a class and add a new method to it only public ones so you can open a class and add new public methods yes yes okay all right so I think I know what this is I've never done it in C sharp or E or in the.net framework so I don't know but I have done things like this in Ruby where you can open up a class and add new methods to a class it was very common thing to do in the small talk world or in the Ruby world or even in the Python world do I think it's a good idea only in certain circumstances it doesn't bother me too much if you can open up a class and add a method as long as you have control over that method that you've added but if it's a method that somebody else might inadvertently call or if it changes state variables that other people are depending upon then I probably wouldn't like it too much like anything else these language these language issues are power tools that you need to use judiciously does anybody wish they had multiple inheritance Oh a few of you do yeah I wish I did I've got it I had it in C++ it was very useful and then I was taken away from me in Java and in c-sharp why why was it taken away because it was harmful don't tell me it's harmful I'm a programmer I know how to program you know if I want to use multiple inheritance that's my fault if I screw myself up but don't you try to protect me by taking language features away that I might find useful I don't need a babysitter I I hate it when they do that now frankly the people who took multiple inheritance away did not do it to protect us from ourselves although that's the story we've been told they took that away because it's really hard to implement in a compiler right it's just too hard they didn't want to face the problem so then they invented this story about how well we're really protecting programmers from themselves an evil thing this multiple inheritance shouldn't do it and that's the same thing with all any of these other things that dinner you know controversial language features I don't need the babysitter I don't need somebody telling me oh you shouldn't use that feature if I want to use the feature I will I'm a responsible adult not an independent irresponsible teenager I live at the bottom of the dam component graph so anybody else I don't see a hand in the air so I'm gonna close the talk thank you very much for your attention see you next time [Applause]
Info
Channel: Rakesh Jaiswal
Views: 4,760
Rating: undefined out of 5
Keywords:
Id: N7agCpAYp1Q
Channel Id: undefined
Length: 61min 45sec (3705 seconds)
Published: Thu Jan 02 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.