CODE ROAST: Yahtzee - New Python code refactoring series!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Full disclosure: it's my code he's roasting, so it's extra fun seeing this video :P

๐Ÿ‘๏ธŽ︎ 6 ๐Ÿ‘ค๏ธŽ︎ u/Endemoniada ๐Ÿ“…๏ธŽ︎ May 22 2021 ๐Ÿ—ซ︎ replies

Very informative! There's so much basic Python stuff on the web but this also touches on design which can really help improve your code. A "gat in de markt" you might say.

What struck me is that the typos (that were nicely annotated in the video) would have been picked up by Pycharm. Is this not a thing in VSCode or did he disable it?

๐Ÿ‘๏ธŽ︎ 4 ๐Ÿ‘ค๏ธŽ︎ u/Armaliite ๐Ÿ“…๏ธŽ︎ May 22 2021 ๐Ÿ—ซ︎ replies

I'm okay saying I'm still a novice about 12 minutes in, because I've never made a successful test application for any of my scripts.

๐Ÿ‘๏ธŽ︎ 2 ๐Ÿ‘ค๏ธŽ︎ u/wrathofnero ๐Ÿ“…๏ธŽ︎ May 22 2021 ๐Ÿ—ซ︎ replies
Captions
this is a new series where i analyze code that you submit and then i take it apart and build it up again like some kind of frankenstein but using software design principles and then hope it still works i'm gonna take you step by step through the refactoring process and explain exactly why i made certain design choices it's time for the in this episode what you think that was over the top you're absolutely right i'm not sure how often i'm gonna do these code roasts in fact that also depends on you if you have an interesting code project you'd like me to review and refactor on the channel join the discord server and submit your project there in this episode i'm gonna work on a game called yahtzee bless you thank you thank you to mcburg for submitting the code for this episode i'll try to be nice yahtzee i'm sure you know it is a dice thrown game where you get points for certain combinations of dice now i'm not part of the elite that has an actual yahtzee scoresheet i have this cheap dutch knockoff called score block by the way this video is not sponsored by the company that makes these because well that would be a bit ridiculous it seems i'm not very good at this let's look at some code so in the original version there are two files there's the yahtzee file and the test yahtzee file that's already a nice thing that there are unit tests in this example if you look at the yahtzee file we have a couple of classes so we have a die we have a hand which is a set of dice and then i'm going to scroll down a bit then we have a class that contains the rules for eltc because there's a couple of them and then we have a scoreboard which contains the scores and it also defines what the rules are and then after that we have a function a main function that is actually the main progress the main process of the game so that's the existing example let's also look at the test so this is the file containing the test so it imports everything from the lc file then we have a couple of test cases for the hand a couple of test cases for the rules so each rule has one test case and then uh that's it basically let me run these tests and you see so 10 tests and the old pass when you run the game this is what it looks like actually this is already pretty nice this is a full house i'm not going to say no to that i mean that's 25 points so i see there's also a problem that if i select number 10 it actually selects number 11 so that's a bug we're going to have to fix so now zero points damn it okay one more time i'm gonna re-roll one two and five and now i'm gonna re-roll one three and four and i'm gonna take the three fours so now i'm actually going to select four because i think that's going to give me the fourth yes okay 12 points nice so i'm not gonna finish the entire game now because that will take way too much time so let's go back to the code so in terms of separation it's nice that there are already a couple of classes that represent different concepts in the game you have to die in the hand and the scoreboard and so on so let's analyze this code now and see where there are some issues so the first thing i noticed is that there are coupling issues in the code let's take a look at the rules and the scoreboard for example so you see that the rules it defines here a set of rules so each particular rule is stored at a particular index in a map and when we go to the scoreboard there is kind of a redefinition of the same thing except then its names so that means you need to make sure that the order here is the same as the order here otherwise your game is going to break another thing is that this rules class actually violates the open closed principle at the moment the way that it works is that each rule has its own function so we have aces twos threes etc four of a kind and so on and so on so those are all the lc rules and just stored here in a map now i understand why you store them in the map because otherwise you'd have to deal with lots and lots of if else statements which which is really bad but let's say we want to create an extended yahtzee game which has special rules then it means we're going to have to dive into the details of this rules class and extend it here and because of the coupling issue we also have to make sure that we're adding it here to the scoreboard so that violates the open closed principle it would be better if we had a kind of strategy like mechanism where we can define what the rules are and basically add them dynamically so when i refactor the code i'm going to do that but in a slightly different way final thing in the rules class is that there is some code duplication here for example each of these fours five six threes they each compute the sum but actually this code is almost the same so probably we can also rewrite this a little bit to reduce some of that duplication a third issue is more on the architectural level if you take an architectural pattern like model view controller for example you want to split the model the data from the view how it's represented to the controller to the logic the logic of the application here that doesn't really happen if you look at what the view is in this particular application that's actually the console we're reading data from the console and printing it out and the problem is that printing things to the console basically happens everywhere so we're printing things in the hand class for example if we're rolling the dice or if we're re-rolling it or if we're showing our hand we're also reading stuff from the from the console input in the hand class same thing for the scoreboard so in the scoreboard class we're printing things here in we have several methods for printing out the scoreboard and so on and then we're also printing things in the main function so as a result where we print things and where we read things from the console that's a bit all over the place and that's problematic because let's say you want to create an ios app version of this so then you don't have console it means you have to change things everywhere in the code you can't use the hand class or the scoreboard class if you're not building a console game another thing is that and that's also related to the architecture is that the data is also not in a single place you have the rules that are defined in the rules class in this map but you also have the rule names which are defined in the scoreboard and the scoreboard also has the points and that architectural issue leads to the coupling that i mentioned in the beginning so we need to separate that a little bit better and finally there's two things that we should improve in the test so let's take a look at this hand test case so this is testing that the number of sides per die is actually set correctly so we create a hand with five dice that each have 18 sides it's going to be a pretty weird die but it could be nice and then basically here it checks that the number of sides equals 80. now that's fine but the problem is that this actually hides a bug if you look at the original die class you see that indeed the number of sides is set here but if you look at what happens when we roll the dice we're actually always rolling a value between one and six so this bug is actually not caught by the test and the reason that it's not called is because this test is actually a kind of trivial test we're only testing that an instance variable is set correctly and we're not testing any behavior and that's one thing that's really crucial with tests to get right that you're not just testing setting data values but that you're actually testing behavior so that's one thing the second thing in this test is that actually this is testing mainly the happy paths so we're testing that asus is correctly computed we're testing that three of kind of four of a kind is correctly computed but it's also important to test the not so happy flows so we should also test that something that's not four of a kind is indeed identified as being not four of a kind i'm going to add one example of such a test later on but let's first look at some other parts of the code so as a first step let's take this die and hand classes and try to make them a little bit better so what i'm going to do is i'm going to create a new file here where i'm going to put the die class inside there we go and we're going to need obviously random generator here so i'm also going to simplify the die class a little bit for example now there is a mechanism where a die when you start has not yet been rolled and here you have to make sure that the die has value etc so i'm going to simplify that because this is actually not used anywhere in the code and just remove that part and just assume that when we create a die it's going to have a value and it's always going to have a value and that just makes things a lot simpler so the first thing i'm going to do here is to call the role method and then let's also solve this book so this should be self. site and for testing i'm going to add an extra optional parameter here so that you can also supply the face that the die is on when you create it so if you supply that face we're gonna assign it to the face instant variable otherwise we'll roll the die this i'm going to remove it we don't need it anymore and now we don't have to have this check here basically this is always going to return this and we're going to simplify this even more because i don't think we need this actually so let's just do it like this what i'm also going to do is add a set phase method mainly because this is easier later on if you want to do some unit tests so that's my adapted dye class let's add a hand file as well so i can remove this from the yahtzee file and then i'm going to take my hands class and put it in here and hand is going to use the die class so i need to import that and actually since python 3 we don't need to put this anymore in our class definition so i'm just going to remove that and i'll do the same thing here just slight simplification there you go this we don't need either and also let's slightly rewrite this so now die expects also a face so let's put that to none so initially it just rolls to a random value and x is not used so we can actually use an underscore here to make it a bit cleaner so that's our initialization method of the hand class now in the hand class we want to clean up a few things so for example here there is a printing message we don't want it to print a message we can put it later on in another place but we want the hand to work separately from the console so we don't want to print anything here that also means that this re-roll method here is actually something that shouldn't be in the hand class at all because this is actually a part of the game process overall so this should actually not be here but in the yahtzee class so i'm going to remove this now and i'm going to put it for now in the yahtzee file and i'll i'll clean this up later so i'm just going to put it here that's not going to work obviously but i'll change it later so i want the hand glass to be mainly responsible for anything related to what you want to do with the hands so you want to roll dice you want to re-roll a set of dice etc so let's create a few methods here that allow us to do those kind of things so one thing that i'd like to have is a method that gives me the indices of all the dice in the hands so if i have five dives i want to have one two three four five and that's useful because we're going to need that to select how many dice we're going to reroll later on and this is actually really simple it just returns a range and the dice instance variable contains how many dice we have so that's going to help us second thing i'd like to do is have a row method where we can identify how many dice we want to roll so here we have the throw method that just rolls everything and we had before the re-roll method that rolls a part of the dice and that's actually what you see here so here it's rolling those dice but i like to create a method that does those two things in one so i'm going to create a roll method so you rename this and then we can supply the dice that we want to roll so i'm expecting dice to be a list and we just need to make sure that every item in this list is within the allowed indices so for any of those elements in dice it's outside of the range then we're going to raise an error there we go and then we're going to roll the dice so i'm going to replace this with another for loop and we're going to roll the dice at those indices we need to subtract one because areas start counting at zero and this dice list is counting at one because that's the user input so also the clear method is not used so i'm just going to remove it it's a nice application of the you ain't gonna need it principle if you ain't gonna need it don't implement it implement it when you need it so then we have the get hand method so in principle the way this is set up is fine but there's a slightly shorter way to do it and this line basically replaces all of these lines so that's a bit shorter and let's see for testing i i'd also like to have a method that allows me to directly set the faces of the die to a certain value and in the in when i write the unit test this simplifies things a lot because if you look at the test now you know this is kind of cumbersome to set the faces in this way another thing that would be nice if if we add a few convenience methods to the hand class so for example often we have to count the number of occurrences of a particular die for example if you want to count the ones or the twos or the zeros or whatever so let's add a method that does that this gives us an array containing all the faces and this has a built-in method called count that counts the number of occurrences of a value so that's all we need to do and let's also add a sum method that's just returns the sum of all the dice in the hand we could compute these things in other classes as well but this just makes it a little bit more convenient so then we have this showhand method that prints the die to the console which is something i prefer not to do because i'd like to separate printing out things from the actual data like classes such as die or hand so what i'm going to do when actually die already has this string method which is actually a better way to do it so also i'm going to add that to the hand and then we're going to use that instead and what we're going to do is create a list of strings that represents each dice information similar to what's happening here but then we're returning that as a string separated by new lines and then create the strings here as a list and now what we can do is simply call the print method on the hand and then it's going to return this and show hand is no longer needed so what we've done now is separate printing out information from both the die and the hand classes which is in the end a bit cleaner now next step is to create the setup for the rules so in the current code rules is one class that has several functions and i'd like to turn that into a strategy so i'm going to add another file here and in order to define the rules i'm going to need to hand because rules compute the number of points depending on the hand that you have and then i'll also use an abstract class to define what a rule actually is and what i'm going to change is that in the current version there's a class that computes the number of points per rule and then later on we have a place where we're defining the name of the rule so i'm going to put those two things together so a rule is going to have an abstract method called name and that's going to give us the name of each rule and it's also going to have an abstract method points and in order to compute the points we need to know the hand so since it's an abstract class we don't provide the implementation of these things yet so let's go back to the rules themselves so i mentioned before that there was a little bit of duplication there so what we can now actually do is create a subclass to cover some of that duplication for us so for a number of yahtzee rules we're simply counting the points as the sum of the occurrences of a particular die in the hands so we count the number of sixes we count fives etc so let's create a class for that that already covers that for us then we can reuse that let's call it same value rule and that's a subclass of rule and we're going to add an initializer method to that and we're giving that a value and the name so we can create this in one go in just a few minutes and then we provide the implementations for the name and the points method the only thing we need to compute in the points method is simply count the die in the hand of a certain value so we're using this count convenience method that i just added before and multiplied by the value so we can now create rules based on this class for example for sixes and then the value is six and then it's going to count the total number of points as the sum of all the sixes and we can do the same thing for aces twos threes etc so let's create another file yahtzee rules where we're going to define all these rules and let's say we want to create a class to represent the asus rule so that's a same value rule and obviously we need to import that here and we're going to give this class an initializer that sets the values to what we want to have so the value is one because aces is one and we give it the name asus and actually this self is not even needed so then we end up with this and i can create same classes for twos threes fours etc now obviously i already prepared this so i can just simply paste them here so now we have the same value rule implementations for each of these different types so you can do the same thing for the other rules basically for each rule we're going to define a class that determines what the name is and how we compute the points obviously i already did that so let's copy that over here so i don't have to bore you with writing and copying over all these rules so this is what that looks like and there's one rule where i did something slightly different i just want to show you quickly and that's actually with the straight so this is how straights are being computed in the original version so basically it looks at the hand and then for each thing it looks whether the following things are plus one plus two plus three and it's sorted so that works but there's a slightly shorter way to do it and i just like to show you how i did it so here you have the class of yahtzee rules so let me scroll down here you have the small straight rule and the large straight rule what i did is i made a class straight that helps me determine whether something is a straight by using this function this expects a list of dice and how i determine whether something is straight is by looking at a specific property of consecutive number lists if you have a list of consecutive numbers so 1 2 3 4 or 2 3 4 5 you can actually compute a sum of those consecutive numbers using this formula so this is a mathematical definition of how to compute the sum of a list of n consecutive numbers starting at 1 and this is a simple closed form solution to compute that now if your consecutive list doesn't start with one but with a higher number so you have two three four five six for example then it's slightly more complicated but it's still easy to compute with the single formula that's written here so the first thing i do is check that the list doesn't have any duplicates because if it has then it's not a straight by default so first i create a deduplicated list of numbers and then i verify that the lengths are the same if they're not the same i'm returning false then i compute the consecutive sum and then i verify that the actual sum is equal to the consecutive sum so with the small straights there's basically two options either the length of the list that i got is already four that means that i put away one die and then i can just check whether that list is a straight in that case i return 30 points if the length equals 5 then i just have to check that either the beginning part or the end part of the list is straight and then i'm also returning those 30 points large trade is even simpler there i just called the is trade function with the entire hand and if that's straight i return 40 points so now let's move on to the scoreboard i'm gonna add another file and i'm just going to copy the original scoreboard from the yahtzee file so that's this there and the scoreboard we have to do a couple of things we have to remove a lot of printing because that's part of the game process and we also want to remove this responsibility of defining what the rules are so that we can use this scoreboard for other games as well so again object is not needed because it's python 3. and we're going to make the scoreboard class really simple that's basically two things the rules and the points and they're both arrays and in order to use this scoreboard we want to be able to register rules so let's add a function for that and we're going to provide it with a list of rules and in order to append those rules to the rules array we're going to use the extend method which does that job for us and when we do that we also need to reset the points so points are zero and i just multiplied with the number of rules that there are let's add a few convenient methods like counting the number of rules that we have and also a method for getting a particular rule so one thing that we probably want to do is that given some rule and a current hand we want to be able to assign points so let's add a method that does that and that's kind of a replacement of this set scoreboard row value the problem here is that this one expects a specific row and that means it's pretty dependent on the specific structure of the list of rules and what i want to do is i want to be able to provide a particular rule and a hand and let the scoreboard itself figure out how to do that so first i'm going to find a row that this rule corresponds to and if that row is not valid so if there are already points that have been assigned we're going to raise an exception and that's actually this one so you also see i'm moving here from printing the result and returning false to actually using the exception mechanism which is a bit cleaner then let's compute the points so there we can use the points method that each rule has and let's assign that and also return the number of points as a result that's assigning points let's add another convenience method to compute the total number of points because we're going to need that if we want to print that information later finally so let me just remove this because we won't need this anymore so now there are some methods that we have to think about what we're going to do with this so there is here a method for showing the scoreboard roles we have a method for showing the scoreboard points and we have a methods for selecting the scoring so again selecting scoring is something that's really more part of the game process and not so much of the scoreboard so i'm going to remove that from the scoreboard and then move it to the elsi file and paste it here and we're going to clean this up later so let me just save that for the moment and then basically the only thing that i think we should do here is have a method that allows us to print out the scoreboard and here there is actually two versions so there's one version that just prints out the rows and there's another version that prints out the rows and the points that you already have so i'm going to combine those into a single method that can do both of those things depending on the parameter setting and let's call that create point overview or something and i'm also going to supply the hand so we can even indicate how many points you would get if you were to choose that row in the scoreboard and default that's num so if you don't supply a hand it won't show that information so let's create an array of strings and add an element to that array for each rule in the scoreboard and that's basically two cases so if there is a hand and the current number of points is zero and the points that are possible with that particular rule are also more than zero it means that the rule is valid then we can display the number of points and here you see why it's nice that the rule contains all the data because now we can simply write rule dot name and in this case we're going to write down the number of points that's possible if you choose this rule let's add three stars if not we simply provide the name of the rules and the current number of points i'm just going to copy this write that here but make it a bit more simple oh and i forgot to actually retrieve the number of points there we go and now we simply print out the number of points and this i'm just moving it over to the yahtzee file which is becoming a big mess now but we'll clean it up in a minute so now our scoreboard is also really clean oh it's expecting a few things that's much better and we don't need to do everything anymore so i'll just remove that so that's our scoreboard and now the yahtzee file we can concentrate here on creating a class that's actually responsible for the overall game process printing out information to the screen etc etc so there's a couple of things i can remove here like this rules class we don't need that anymore so i'm just going to remove all these rules there we go we don't need this and i'll probably also need to add all these imports so what are we going to need we're going to need a hand here and the scoreboard and the yahtzee rules and let's just import everything and then let's create a class where we're going to put in the methods that represent the main process that's part of the game so it's called x class yahtzee game it's going to have an initializer and in the initializer basically we're going to put the stuff that was in this main method here so i'll copy this over there and then we begin by instantiating hands and the scoreboard just like in the original game but we're just storing them as class instance variables and these are default values so i'm not going to put them here so i'm creating a hand and a scoreboard and now this is also the place where we're going to define what the rules of the game are and for that we're going to call this register rules method and now we simply create the instances of all the rules that we defined before so now let's set up the overall process of the game and for that i'm going to add a play method and the main responsibility of the play method is to make sure to govern the overall process of playing the game so the overall process is to keep going until the scoreboard is full so that's the part that you see here and then we show the number of points and quit the game so i'm just gonna copy this over for the moment and then refactor it later on it's just going to move that to the play method and we need to change the logic here slightly so actually going to make this very simple and it's just going to be a for loop that's going to run the number of times that we have rules on the scoreboard and that's where our convenience method for counting the number of rules comes in handy so that replaces that while loop and now this part this is actually a turn in the game so let's separate that out to another method and here we need to do a little bit more work because we're also responsible for printing the things and we remove that from the other classes so we have this reroll method here so let's go to that method definition so that's actually this so this is actually kind of what a turn is so i'm just going to copy this over and i'm going to put that stuff here there you go and now let's see so we start with rolls as zero and let's say that initially we're rolling all dice so i'm going to have a variable selected dice and that's uses the all dice convenient methods from the hand class that i defined in the beginning and then this check i'm not going to do here i'm going to do that a bit later so while true and then i'll break out of the while loop at the appropriate places so what do we need to do well first we need to roll the dice so i'm just going to remove that here because we don't need that anymore so in a turn i'm going to roll the dice so this is where i can print some information and i'm going to use my generic roll method that takes a number of dice in this case it will be all the dice so that's in this variable and then we can change that later on and because a hand has an underscore underscore str method i can actually simply print it here like so and roles we keep track of how often we have rolled until now and that means if we reach the maximum number of roles we're done now there we go and then optionally below we're going to ask the user to reroll and that's basically this whole part so we want to let the user choose which dice to reroll and let's add another method that does that for us and basically that's going to be this part so i'm just going to copy that over and create a new method that's going to contain this and here we want to ask the user to enter the dice to reroll and i'm going to put that in a while loop as well so that if there is an arrow we can retry again and again until the user gets it right so you will ask the user to input which dies to reroll i'm not going to change this but here basically what we need to do is return simply all the dice and we can use the all dice convenience method for that in the other case we're parsing and splitting the re-roll just like in the original game and we just need to handle a few specific cases here for example this one so if we didn't provide any reroll value or there is a zero in there then we assume that the player doesn't want to reroll any dice so we return the empty list if not we return the list of desired rerolls and these things we actually don't need here and the continue is also not needed so let's go back to the do turn method so that should call the choose dice reel so here we're choosing which dies to re-roll if that's the empty list we're done because the user doesn't want to reroll any dice and now we need to do the last part which is select the scoring and show the points so the select scoring method now returns the rule and let's create a select scoring method that does that job for us and for that i'm going to copy over this method just going to move it over here and we don't need to pass because that's actually an instance variable and here we basically need to refactor this code a little bit so that it works with the scoreboard directly so the first thing we want to do is show the number of points so we're going to make a methods show scoreboard points so we have these two actually and let me just copy this one this one we're going to use for two cases either we want to print out just the number of points or we want to also show what possibilities there are and we did add that to the scoreboard because here we have this create points overview that actually takes the hand as a parameter and i see that i i forgot something here so i should just make this the right variable names and then return that as a result so let's call this method with optionally the hand so we're going to pass that as a parameter and then optionally we can leave it out and that will only print the scoreboard without the potential points so we're still going to print this out because that looks nice on the console but then we're simply going to print the scoreboard create points overview results and this stuff we don't need them actually so that's for showing the scoreboard points and we need to hand here because we're going to select the scoring so we want to show the potential points to assign and then we're going to let the player choose which scoring to use and we're going to simplify this a bit because here you could leave the input empty to show the available roles i'm just showing it always so that kind of simplifies the way to do this so again a while loop and we break out of the while loop when we got the correct values and what i'm going to do is uh simply copy over these things and revise it a little bit so that it works with the new scoreboard system so i'm not going to bore you with that part i'm just going to remove these things and copy over what i already prepared because this video is starting to be pretty long that's simply retrieving the rule of the scoreboard now here the rest is actually pretty straightforward so now you can compute the number of points and for that we need the rule that was selected and a hand and then we can also print this there we go and finally we can call again show scoreboard point without passing the hand to show what the new scoreboard looks like and that's basically it so now these things i can remove this i can remove and this we can also simplify so the only thing we need to do here is create the lc game and then start playing this is actually not needed because this already the end of the script so i'm just going to remove this oh small error i still need to fix this obviously so this is just gonna show the points and then do this we can also simplify because we already have a convenience method in the scoreboard to compute what the total number of points is so i'm just going to remove all of this there almost there yeah so let's run this game again it works really in the same way as before except we've much better separate everything do you see this i just got a large trade so i want to keep that obviously and let's see yeah give it to me a lot straight all right great so what happened in this new version so first responsibilities are much better distributed we have the yahtzee game which is responsible for all the printing and the overall game process and everything we have the rules which are here on separate classes if we want to have more rules we can add more rules it's not a problem the scoreboard is independent of the kind of rules that are and there are a couple of classes like the rule abstract class that defines what rule looks like and we avoided some code duplication by using subclasses and then we have the very generic die class and hand class that allow us to manage a hand of dice so the yahtzee game itself as you can see is now responsible for defining what the rules are which makes a lot more sense so everything is in the same place that it's much cleaner and that means if you want to have a custom yahtzee game you simply add an extra rule here and then the rest of the software will still work without any issue as an example let's add a custom fibonacci rule i'm just going to copy over this class to define my new rule so that's fibonacci and i'm also returning that as a name and then in the points function i'm going to compute whether the hand is a fibonacci okay how many points is fibonacci well let's say 100 points sounds good i'm going to save that so now i have my new rule and now the only place where i need to change anything is in the lc file and i simply add it here so of course i need to import it and then i add it to the scoreboard there you go that's the only thing you need to do now to register a custom rule and all the rest of the game will simply work there's a couple of limitations to what i did so i tried to separate the printing more from the data which is what happened but the game process which you could kind of see as the controller is still mixed up with printing so that means that if you look at it from model view controller point of view that the view and the controller are actually still kind of mixed up so i think it's actually it would actually be nice to split up this yeltsi game class even further and separate the printing of the game from the process of the game but this video is already getting really long so i don't want to spend any time on that if i were to turn this into let's say a commercial version of the game i would definitely work on that part as well second thing is i didn't write any test for the ui i think having ui tests would also be really useful these are a bit harder to write than the tests you would do with the dice and the hands but it's still possible to do it i might cover that in another video actually the tests are also now pretty simple because what you can do let me show you just one example so i could import the yahtzee rules and if i wanted to test the asus rule i could simply do that here and this is where the setfaces method comes in handy so we create an asus rule object and let it compute the points for the hand and it should be equal to five so there's no longer a for loop needed which makes these writing these tests a bit shorter you could do this for all the different kinds of things i'll do one more let's say we have the full house rule so i can do something similar so we have something like this and i mentioned in the beginning that it's also good to test the not so happy flow because this is the happy flow so you should also test that something that's not a full house is also properly identified as such so let's do something like this for example and then we expect this to be 0. when you convert all these tests to the new format so then this is basically what you're going to end up with so if your die test cases your hand test cases rules test cases and optimally you'd also like to add user interface and scoreboard test cases here all the code that i worked on in this episode is available in a git repository i put a link in description thanks again to macberg for supplying the code i hope you enjoyed this refactoring session it's been a long day i think i'm gonna crack open the beer and chill out a little bit make sure to subscribe if you haven't done so so don't miss out on anything thanks for watching take care and see you in the next video
Info
Channel: ArjanCodes
Views: 27,477
Rating: 4.9445887 out of 5
Keywords: python code refactoring, learn python 2021, code refactoring, code refactoring python, python tutorial, clean code, design principles, software development, learn python 3, programming best practices, refactoring python code, refactoring python, python refactoring exercises, python refactoring tips, design principles in software engineering, code refactoring exercises, code refactoring tutorial, programming best practices python, Refactoring python example
Id: l7E3y4te7sA
Channel Id: undefined
Length: 45min 58sec (2758 seconds)
Published: Fri May 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.