Transcript for:
Refactoring Techniques for Cleaner Code

knowing how to refactor code is one of those fundamental skills that are going to make you a better software engineer so that's what we're going to discuss in today's video with a practical refactoring exercise I'm going to start by briefly explaining what refactoring is and why it's valuable and I'm going to walk you through the refactoring exercise that we are going to be doing refactoring is a technique for restructuring existing code without changing its behavior and this is the critical part when it comes to refactoring and also the part where most people make a mistake and that is you are not allowed to change the behavior of your code now what is a good way to know that you didn't change the behavior one option is that you are very careful while refactoring however you can't always be sure that you're are going to be focused on what you're doing so the best solution for safe refactoring is to have a lot of tests and we're going to discuss this when we get to the Practical part another question you might ask yourself is why do we need refactoring in the first place we don't practice refactoring just for fun of it the main idea behind refactoring is to improve the quality of the existing code we achiev this by refactoring the code to make it easier to understand and cheaper to modify when we need to make updates to the same code in the future as with anything in software engineering refactoring is a skill and practice definitely makes perfect so that's what we're going to do in today's video let me walk you through the refactoring exercise that we are going to do we're going to be solving a tennis refactoring CA that contains many exercises inside this is the GitHub repository containing the refactoring CA and I'm going to leave the link to this repository in the description of this video you can see that there are implementations in many popular programming languages we're going to be solving the example that is built in C and I'm going to walk you through the setup and what we need to achieve with each exercise this is what the C refactoring cutor contains out of the box there is a tennis class library that contains an i tennis game interface with six implementation of this interface there is also a test project that contains the test testing the6 implementations that we have let's go back to the interface for a moment and let's discuss the methods that we have here there are two methods one called one point and another method called get score the onepoint method should be called with a player's name and it should mutate the state of the tennis game instance to update the score for the player then won the point the get score method should give us the current score based on the two scores that the two players have if we go back to our tests you can see that the test setup is always the same there is player one and player two and each test case accepts some preconfigured data so we have the points for each of our two players and then what is the expected score given the points for each of the two players this is checked with the check all scores method so let me walk you through what we have here and when this method is going to do is it's going to play out the game by assigning points to each of the players and finally is going to determine if the expected score is equal to the score returned by the game instance there is also the test data generator class which contains many test cases that we can use to test our game implementations and if you aren't familiar with tennis there is a very peculiar scoring system where these scores are denoted with 0 15 30 and then 40 the score of zero is called love then you have 15 30 40 if we run into a situation that two players have the score or 40 we call that aduse at this point the next player to win a point is going to gain the advantage so we call this Advantage either player one or player two and to win you need to reach 40 before your opponent does or if it comes to a use then you need to win two more points than your opponent so you can see that the test data generator contains many test cases based on the player scores and the expected score at this point in the game so now let's check out some of the implementations and see how we could refactor them to make the code if easier to understand and easier to update in the future this is the tennis game one implementation and you can see what the onepoint method implementation looks like as well as the method for fetching the score based on the Player points and let's see how we could refactor this to make this code slightly better the one thing that bothers me here and this isn't necessarily A refactoring but more of a code style preference is the lack of curly braces when it comes to if statements or even Loops I always prefer to have these curly braces that clearly represent the code block so the next thing that bothers me when it comes to the onepoint method implementation and you can also see this from my IDE in this case Visual Studio you can see that the player one and the player two name fields are unused I can tell this because they are grayed out but also if you check out the implementation you will see that they are not used so let's start with these fields and the next thing that we could improve here is to be consistent when it comes to naming so you can see there are variables here with M then Dash then score one and then we use another naming convention for player one and player two names the naming convention that I like to use is an underscore for private Fields And Then followed by the field name so I'm going to use the rename refactoring to make this update and then let's add the underscores here and notice that I'm using the refactoring so that it updates any references inside of my class I also don't like using redundant code so I'm going to get rid of the disc keyword because it's not required in the Constructor and then the next thing that we could do is to make the one point method not use a hardcoded name for player one instead let's actually use the player one name which we have as a field another suggestion that I'm getting from Visual Studio is to make this field read only because we are only assigning to it from The Constructor and we aren't changing it anywhere inside of our class we can also do the same for the name of the second player so that's pretty much it when it comes to the onepoint method it's just an if statement that's going to update the score of each of the two players and then increase the score by one another thing we could do here is to rename these scores to make it clear that these are player scores this could also be considered redundant because we already know that this is a tennis game and what the score one and two represent however let's keep things consistent and use this as our naming convention and then let's scroll down to the get score me meod and see what we can improve here another thing that I can see immediately is that the temp score method is declared at the top of this function but it's only used down here so what I can do is move the definition of this variable close to where it's used so that it doesn't clutter my code and now let's see how we can improve the get score method which is almost 50 lines of code let's tackle this one if statement at a time and we should definitely be running our tests to make sure that we didn't break anything so let's go ahead and execute our test cases you can see we have a lot of them I'm going to run all of the test cases for all of the implementations and we're going to make sure that all of our tests are passing so at this point it is safe to proceed and update and refactor the get score method and we're going to be using our tests to keep us safe from not introducing any unwanted changes the first if statement here is handling the situation when the two players have the same score so in that case it's going going to return either love all 15 all 30 all or du depending on the current number of points so one thing we could do here is to refactor this into a switch expression just to make this a little bit more concise so I'm going to do that through Visual Studio the shortcut for this is control and Dot and then you can just execute the convert to switch statement command and this is what we are going to get we went from some 15 lines of code into something like six lines of code which is already an improvement and then the next thing we could do is take a look at how we are using this score variable and you can see that we are assigning to the score so that we can return it from the bottom of this method so why would we have to wait to go through all of this code we won't be executing it but we have to read it in order to return the score so what we could do is to just immediately return the result of this switch expression and what that's going to do is make the L statement here redundant which means we can clean it up so let's go ahead and remove that and we are only left with an if statement here checking the first condition and then from here we have a few options we could introduce a variable to give this condition and descriptive name we would call it s we could also extract this into its own method if we wanted to but I'm not going to focus on that at the moment and let's see how we can improve the rest of this method I'm going to start by adding some curly braces here to make it obvious what are the cases that we have with the IFL statements and whenever you have an IFL statement like this you can probably convert this into a switch statement or a switch expression in this case Visual Studio is again letting me know that I can convert this into a switch expression so that's what I'm going to do and then from here I already know that I want to return this value immediately so I'm going to get rid of the score and just write a return statement this also makes the last L statement redundant so let's get rid of that and you will notice that this is also removing a level of indentation that's no longer needed let's move the score below to move it closer to where it's used and then let's discuss what we have in this second statement what we are checking here is if the two players have four or more points in this case we ran into aduse and the players need to win two points more than the opponent in order to win the game instead of a meaningless name like minus result you could rename this to score difference and then depending on which player has the advantage we're going to return a different value so if the player one has more points the score is going to be positive and if it's equal to one we're going to return Advantage player one if it's minus one then that is an advantage for the second player if the score is greater than or equal to two then this is a win for player one and the only remaining option is that we have a win for player two because we already handled the case when the two scores are equal a few more things we could improve and this also goes for the first witch expression here is to introduce some constants for these numeric values because they don't convey any meaning we need to have internal knowledge of how our scoring system works in order to understand what two means what is minus one here and so on I'm not going to be doing this but I'm leaving this as a remark for you when you're practicing this refactoring CA and then let's go into our last block of code here so what is going on here it's a bit difficult to decipher so let's add some curly braces they are already here but they're just indented on one line and then let's try to figure out what is going on here we have this variable that's holding the temporary score and you can see that we are assigning this to either the score of the first player or the score of the second player and then this Loop is set up so that it's going to run only for two iterations so this is interesting in the first iteration we're going to assign the temp score to player one and in the second iteration we're going to update the score with a dash and then assign the temp score to player two and the use for temp score is this switch statement here is going to append either love 15 30 or 40 to the current score and this value is based on the score of the two players so essentially what we are trying to do here is get a score like love 40 for example and the appropriate number of points for this would be 0 to three so what we can do here is to move some of this code outside of the for Loop for example the switch statement here could be moved into its own function if you right click this code you will be able to extract this into a method and if you're using something like resharper you can have even more refactorings so let's use the extract method refactoring and move this into its own method the only argument I want to pass to this method is the temp score and we're going to rename this after creating this method but let's first do the refactoring I'm going to rename this into just player score and then you can hopefully understand what this method should be doing so based on the player score I want to return either love 15 30 or 40 so I'm going to replace this with return statement and then I can get rid of the score variable so let's go ahead and remove that I can go ahead and remove this return statement and then I need to add a default statement so for example the default statement could be the case for returning 40 and now I can convert this into a switch expression to make it more concise So based on the player score if we get zero I'm going to return love if we get one I'm going to return 15 and so on and what we want to do is to append this value to the current sore before returning it but if you take a closer look essentially what we are doing is iterating twice through this Loop and then just calculating the score for the first player assigning that adding a dash and then calculating the score for the second player so why not just write this in a more concise way let's calculate the score for the first player add a dash between and then let's calculate the score for the second player and now I can get rid of this entire for Loop and this is what I'm left with of course I need to run my tests again to make sure that my refactoring didn't break anything and you can see that my tests are passing from here you can continue to refactor this implementation into something that is more meaningful to you let me walk you through the other implementations that are here that you can use to exercise so there is the tennis game 2 implementation which is quite interesting this is how the get score method looks like here's the first case where the two players have the same number of points then we have the second case where one of the players has the lead and so on so you can see that the implementation is quite complicated and the refactoring here would be to simplify this as much as possible there are also some methods like set P1 score and set P2 score which should update the score for the two players but as you can see these methods aren't used I can see that they have no references so for example what I could do is to delete these two methods and rerun my tests to make sure that I didn't break anything so you can see that my project is building and you will see that the tests are also passing so one part of the refactoring could be just removing unused code then let me show you tennis game free which is definitely more concise but there are still some improvement points that you could make here for example you could update the names of the fields to make them more descriptive and so that we can more easily understand what they represent obviously P1 and P2 are the points for the first two players and then we have the player names in the get score method there is this interesting part of code here where we have an array containing the possible values for a given number of points and then we access that based on an indexer so P of zero would match the score of love and then we have P of one matching 15 and so on and this one could be very interesting to refactor so I said the first thing would be to update the field names and then we could do some fun stuff with this logic here for example we could extract this into a static field so that we don't initialize it every time that we call get core and this could also be a slight performance Improvement tennis game 4 is the Enterprise Edition implementation of the I tennis game so you will see that it contains a lot of complexities many classes interfaces abstractions so this is a real mess when it comes to refactoring and honestly it's very complicated to even just understand what all of these classes are doing so this also goes to say that some of the best practices that we are using when it comes to Enterprise development aren't necessarily that good when it comes to code clarity the get score method itself looks relatively clean you can see that we are creating an object hierarchy assigning some objects into the Constructor and in the end we call get result to get the final result however understanding what all of these steps are doing is the complicated part Dennis game five is one of the more concise implementations the get score method is just a switch statement covering all of the possible cases but the prerequisite is that we update the scores for the two players and limit it to up to 4 four points now this while loop here is something that you could improve and the challenge here would be to update this score for the2 players without having to use this Loop and then tennis game six is another interesting implementation that you could try to refactor the main idea here is to practice the extract method refactoring so you could move all of this code into one method and then extract this code into another method and then extract this code into another method or two depending on what you want to do and this will leave you with three concise methods and it would also simplify the get score method implementation I hope you found this refactoring C interesting and let me know in the comments if I should do more refactoring videos like this one if you want to learn more about refactoring best practices then you should watch this video next also check out my clean architecture and modular monolith courses and until next time stay awesome