Cohesion and coupling: write BETTER PYTHON CODE Part 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
today i'm going to help you write better code by looking at two important software quality metrics cohesion and coupling first i'll talk a bit about what those metrics mean and then i'm going to take you through a detailed example in python and show you how you can improve your code by taking these metrics into account in your design make sure you watch this video till the end because what i'm going to show you is something you can apply to all the code you write in any programming language and it's going to help you write high quality code that's easy to maintain and easy to reuse so are you ready let's dive in i mentioned two important software quality metrics cohesion and coupling they're both more higher level concepts and they say something in general about how easily your code can be changed or extended let's first look at cohesion cohesion is the degree to which elements of a certain class or function belong together for example take a look at this function already the function name should be red flag but it's clear this function has weak cohesion it does a lot of different things that do not really belong together a function with strong cohesion on the other hand has a clear responsibility it has only one task an example of a function with strong cohesion is the cosine function in python's math library it does only one thing compute the cosine of a number and that's it having strong cohesion is important it makes your code easier to maintain and understand code that does one thing only is also a lot easier to reuse than a giant function doing lots of different unrelated things the other metric is coupling coupling is a measure of how dependent two parts of your code are on each other take a look at this example this is a function that checks whether an email is legit by looking at various parts of the header the code in the function directly accesses data that's deep in the structure of the email object this means that this function is highly coupled to the email object having high coupling is problematic because changing something in one part of your program that means you need to change things in multiple places in this example if the structure of the email object changes you'll have to rewrite the check email security function as well now there will always be some coupling in your code because the various parts of your code need to work together somehow but the more coupling you introduce the more difficult it becomes to maintain your code in order to solve the coupling issues in this case you could either pass along only the data that the function needs instead of the entire email object or you could move this function inside the email object since it's so directly related to the data in the object copying and cohesion are important metrics for software quality unfortunately you can't simply compute a number that tells you how cohesive or how coupled your code is it comes down to you as a developer to understand the structure of your code well being able to analyze your code in terms of cohesion and coupling and improve it in general you need to learn to make the right decisions when you're designing a piece of software you will get better at this as you become a more experienced software developer but it's a skill you need to train yourself in to help you make progress in this direction i'll show you how i do this i'm going to walk you through a code example analyze its cohesion and coupling properties and then i'm going to improve it after watching this video you can apply these ideas to your own code right away and you'll be amazed at how much you'll be able to improve the quality of your code before we start though give this video a like if you're enjoying this content and here's a question for you can you think of a software library that's badly designed in terms of coupling or cohesion let me know in the comments below alright so this is the code that we're going to take a look at today basically consists of two classes there is a vehicle registry class and there's an application class vehicle registry is basically just a container for two helper methods one method you generate an id for vehicle so it takes a length parameter and the second method that generates a license and you have to give it the id as a parameter and then it gives you a license plate number back the application class has a single method called register vehicle that takes a brand name and this reads the vehicle method does a couple of things so first it creates an instance of this vehicle registry class then it generates a vehicle id of links 12 and it uses that id to generate a license plate next it computes the catalog price of that brand of car so depending on the brand you choose a different price i have no idea if these prices are anywhere near what's a reality but it doesn't matter for now and another thing is the tax percentage so by default it's five percent if it's an electric car so if it's a tesla model three or volkswagen id3 then the tax percentage is two percent now these tax percentages are also wrong i mean i know in the netherlands you pay way more tax than this for now let's just follow this example it doesn't really matter what the exact numbers are so then when you know the catalog price and you know the tax percentage you can compute the tax that you should pay and then finally you print out all the information that's related to this vehicle registration so that's the brand name the id that was generated the license plate and the tax that you should pay and then finally i create the application and i register a vehicle so if i run this program you see that there's a bmw 5 registration with an id and a license plate this is the dutch license plate structure probably in other countries this is going to be completely different but it doesn't matter and there is the tax that you should pay so you can see that i can also change this to a different type of vehicle so let's say i'm registering a volkswagen id3 and then i run the program again and i get a different result yeah in the netherlands you definitely pay a lot more tax than this so that's the overall structure of this simple application there's a problem though with in particular registered vehicle as you can see it's doing a lot of different things it generates an id and a license plate it computes a catalog price tax percentage then it computes text and it prints out all the registration information so it's a lot of different things that this method is doing it means that this method has very low cohesion it has way too many responsibilities it is also high coupling because it's directly relying on implementation details of this vehicle registry class in this example register vehicle has to know that this generates an id and that you have to pass that id to generate vehicle license so this high coupling means that if i change anything in vehicle registry i'll also have to change the register vehicle method there are other problems in the code as well that occur because of this low cohesion in particular for example at the moment it's very hard to add another brand of vehicle because then you have to sift through this if else statement add an extra line here that for that particular brand and type also if it's an electric car you have to change things here overall that's not a very neat way of setting this up so let's try to make this code actually a lot cleaner and a lot better by looking at these metrics cohesion and coupling and try to find a way to make this code a bit more easy to use what i like to do generally in this case is look at the information where is information stored and how is it accessed and then when you know that when you have defined the logical structure of your information you can also start to group the code around that overall that leads to lower coupling because the code is closer to the information that it uses and also allows you to have functions methods that have higher cohesion because they can do only one thing with that particular type of information this actually quite close to what greg larman says in his book about object-oriented design where he defines so-called grasp principles of software design he includes also cohesion and coupling in there but one other thing that he mentions is that you should look for an information expert so basically where is the information that your application uses centered and that's what we're also going to do here so if you look at this example you see that the data is actually not stored logically because here there is a direct coupling between brand name and catalog prices which is really bad and also if you look at this how the tax percentage is computed actually the text percentage depends on whether a brand is electric or not and not on this specific brand name so we're actually missing some information here another thing is that there are actually two things here one is that we have brand information such as what is the catalog price of a bmw 5 but we also have vehicle instance information an id of a particular vehicle or a license plate of a particular vehicle and it's probably a good idea to separate these things so we have one place where we have vehicle brand information that we use to then register specific vehicles so let's try to separate this information into two classes a vehicle and a vehicle info [Applause] so i'm just going to put the member variables on the top so we keep track of what they are so a vehicle info object should have a brand name it should have a catalog price and to solve the problem with determining the tax percentage we should also store whether this is an electric car brand so you see just for clarity i'm adding these type hints here that you can use in python because it helps me understand what the structure is of these objects so this is basically the data that is related to the brand so we have brand name catalog price and whether it's an electric car or not then we also have an actual vehicle instance let's call that vehicle vehicle has an id that would go to generate as well as a license plate and finally what we're going to do is we're going to keep a reference to the actual brand information so that we know what kind of vehicle this is so vehicle itself has a reference to the actual information of the brand so whether it's electric the catalog price and the brand name so this is the data that we're going to be dealing with in this application so i'm going to continue with this work just in a little bit but first let's also take a look at this coupling problem that we have in register vehicle the problem is that register vehicle has to know these implementation details about generating ids and generating a vehicle license and that's that's a bad thing we want to avoid that so one thing that we can do is we can try to move these things to the vehicle registry class and try to do more things there because clearly vehicle registry is dealing with generating ids and licenses so it would be useful to put as much as possible in this class instead of in the register vehicle method so what we can do to solve this is that actually we are going to add a method here that creates a vehicle for us a vehicle has an id and a license plate vehicle registry generates those things so it makes sense that actually vehicle registry is also responsible for creating this object so let's add a method here that's called create vehicle and that's going to need a brand name so the first things that we can do in create vehicle is actually generate the id and the license plate so these two lines here we can actually move them over to this method here and then obviously we're not using registry but we're in the class so we can use self so this gives us a vehicle id and a license plate now we need to create a vehicle but in order to create a vehicle we also need the vehicle info so this means that as a part of vehicle registry we need to also keep track of these vehicle info objects so let's do that so let's create a bunch of these vehicle info objects so what i'm going to do is i'm just going to create a variable here called vehicle info and for now i'm just gonna make that an empty object and then i'm going to add a method for creating vehicle info objects so for that i need the brand whether it's an electric car and the catalog price and i'm using this object here as a dictionary so that i can find these vehicle info objects depending on the brand that i put in so i added this add vehicle info method that puts brand vehicle info inside this dictionary then what i'm going to do is add a simple initializer here and you can also do this in a different place if there are lots of vehicles for example i can imagine that you're actually reading this vehicle info from a database and not from a dictionary like this so probably in a real world application this would look different but for now let's just add a few examples of vehicle brands in this initializer so i'm going to add the tesla model 3 and tesla is obviously with a capital letter i don't want to piss off elon musk it's electric and it costs 60 000 i don't know what euro dollar bitcoin anything and let's add a few more all right so there we go so now if we create a vehicle register object it's going to fill this vehicle in for a dictionary with a few basic brands and then here when we call create vehicle we can now use the vehicle info from this object to create a vehicle instance so i'm going to add one more line here so i'm going to create a vehicle and that vehicle is going to need an id and a license plate that i just made there and we're also going to need the brand info there you go and now the only thing i need to do in vehicle is to make sure that it actually has an initializer function that accepts this information so let's add that as well and actually i see that i forgot to add this initializer function to vehicle info as well so i should also add it here all right so now what i can do in the register vehicle method is that instead of doing these low-level things here i can now use the vehicle registry to create a vehicle so that's just a single line of code now and we're going to store that in a variable there so these things we don't need anymore now what we didn't yet look at is this whole story of computing the tax based on the catalog price etc so now we also need to move this to a more logical place if you look at where the data is for these things so what we need in order to compute the tax that you pay is the catalog price and the tax percentage that means if you look at this vehicle info and vehicle class that vehicle info is actually the logical place where you should put this because here we have the catalog price and we know whether it's an electric car or not so let's add a method here that computes the text so i'm just basically going to put the same thing more or less that i wrote here so let's copy this but we're going to be a bit smarter than in our first version because we're not going to look at specific brands but we're just going to look at whether this is an electric car or not so if it's electric then tax percentage is two percent and then in order to compute the the actual tax that somebody should pay we can then simply multiply the tax percentage with the catalog price and that's our compute tax method so let's also remove this code here because that's already in another place now you see you want to print out the vehicle registration information so this is where you're going to need things like the license plate the id and the payable tax printing out information is actually now also two things so we have vehicle info things like the brand and the payable tax and we have vehicle instance like the id and the license plate information so what we can now also do is simply put in two print methods vehicle info could have a print method that prints out the brand generic brand information and then vehicle could have a print method that prints out actual vehicle instance information so when you look at the vehicle info what do we need to print here well that's the brand name and the tags that you should pay so let's make a print method here that does exactly this and i'm going to use string interpolation because it's really useful so there i'm going to print out the brand of the car and i'm going to print out the payable tax and this is where i call the computex method there there we go so that's the print method in vehicle info and i can add a similar one to vehicle and i'm going to pull a really nice trick you'll see what i mean so first i'm going to print the id and then i'm going to print out the license plate there we go the license plate and then now because we have access here to this info object i can actually call the print method from vehicle info inside vehicle so that i print out the brand information as well there you go so now when i have a vehicle and i go print it actually first outputs an id and license plate and then it outputs the information of the brand so what i can do now i have here in my register vehicle method i can now remove all this low cohesion printing stuff and then i can replace that by simply calling vehicle.print and now let's see what happens when we run this code normally when your developer you just typed out a lot of code this is never going to run the first time you try it so let's see what happens ah no yeah that's what i thought so it seems i forgot here and let's see oh yeah of course i forgot this and let's see what happens now so we get even more problems so i'm getting a problem that electric is not defined so this is happening where that's probably let's see so you see i'm debugging this on the fly ah there you go okay so what do we got now yeah okay now we get something so basically this gives us the exact exact same result as before so let's see what happens if i now replace this again by bmw five and let's run this code again and there we go we get the exact same payable tax there's one more thing we can do to make this code even a little bit better actually it's kind of strange that register vehicle is responsible now for creating the vehicle and for also printing out vehicle registration information instead of doing all these things in one method we could actually return the vehicle as a result from registered vehicle and then print out the information somewhere else so that means we simply change this to a return statement so it simply returns the vehicle that you created in the registry and then we need to store it here and then we are going to print out the information here and this is going to do exactly the same thing as before so now actually the register vehicle method is has become very simple and we're very explicit about that we want to print out the information and we can replace this later on by i don't know if we want to do it in a gui or something and as a result we won't have to change the register vehicle method so that's a very nice thing so quick recap if you look at the overall code now that we wrote we stored the information in a much more logical place by splitting it into vehicle brand information and vehicle instance information and we attached methods to this that do something with that particular data so if you look at each of these functions now so we have more functions before we had only a few two in vehicle registry and only the registered vehicle method here now we have quite a few different functions but as you can see each function is basically only a few lines of code and each function is very specific in what it does this just computes the tags this just prints out brand information this adds vehicle info to a dictionary this creates a vehicle instance each method in this example has basically only one responsibility and that even holds for the register vehicle method so this this has one responsibility creating a vehicle instance and the printing is left out for the other part of the application so our functions have a single responsibility a very high cohesion and functions are so close to the data that they manage so basically compute tax is part of vehicle info which already contains the information that you need for completing the tax so that means that coupling here is also pretty low of course there's always some coupling because register vehicle needs to know that the vehicle registry has a create vehicle method but that's much easier to handle than the coupling we had in the first version of this application and the nice thing is because we set it up this way now it means that the code is also much easier to extend or to maintain for example if i now want to add a new brand i can simply add here one single line and i'm done so let's see let's add a another tesla [Music] tesla model y i think this is more expensive oh you guys are going to completely grill me over not knowing my electric vehicle prices anyway so now i added a tesla model y and i can also register a tesla model y here and there we go and we pay 1500 dollars in tax which is probably not really true so because we set it up in this way adding new vehicles here is pretty simple to do also other changes are much easier to to do for example if you want to change the tax percentage for electric cars you can simply go in the compute tax method and do it here arguably you could even decide to split this compute tax method into two methods one for determining the tax percentage and one for actually computing the tax that you should pay based on the catalog price i hope this code example has helped you understand what cohesion and coupling is and how you can use these two metrics to write better code i showed you an example in python but obviously you can apply this to any programming language in the coming weeks i'm going to post a number of clips here to look at a variety of software design techniques so be sure to subscribe to my channel so you don't miss out on anything thanks for watching take care and see you soon [Music] you
Info
Channel: ArjanCodes
Views: 65,491
Rating: 4.9779935 out of 5
Keywords: how to write better python code, how to rwite better python code, write better python code, improve python code quality, coupling, cohesion, grasp design pattern, object-oriented design, Improve code, write clean code, clean code, how to write clean code, coupling and cohesion in software engineering, clean code python, grasp design patterns, improve coding skills, object-oriented design process, object-oriented design and analysis, cohesion and coupling, coupling and cohesion
Id: eiDyK_ofPPM
Channel Id: undefined
Length: 26min 14sec (1574 seconds)
Published: Fri Jan 22 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.