Effective PyCharm Transcripts
Chapter: Refactoring
Lecture: Finding duplicate code

Login or purchase this course to watch this video and the rest of the course contents.
0:01 Let's kick off this refactoring session by first looking at the structure of our code. I still have or git repo up here, it says project course,
0:10 which is not amazing, we'll fix that in a minute. And I've just decided to create one project that opens all of it,
0:15 and I have copied in this slightly altered Wizard code from my Jumpstart course remember, it's called the wizard code,
0:23 because over here we have Creatures and Wizards which derive from them and we have Small Animals, and we have Dragons, things like that.
0:32 So it's a little game, we're going to make this game a little bit better, partly by removing some issues I've introduced.
0:39 Let's just say we haven't really looked at this code and I would say probably the most significant issue
0:44 you're going to run into with refactoring is duplicate code. Second to that, maybe tied with that is extremely long methods
0:52 or extremely large classes that should be broken apart, and it turns out the solution for both of those is really often the same.
1:00 So, let's start on the duplicate code side. Now, if we look at refactoring up here, you'll see there's a hotkey that always let us refactor anything,
1:09 so if I was down here and I highlight this, I could hit CTRL T on Mac, I think it's something else on Windows,
1:19 we can pick, extract variable, extract the constant, extract a parameter, all these different types of things here.
1:26 But let's take a moment and not necessarily use this, we could extract different things, pull members up and down, move,
1:34 we'll talk about what that is, change a signature methods and so on. But before we apply the refactoring, let's ask where is the problem?
1:42 Is there a problem? Well yes there's a problem, there's always a problem with code,
1:46 the question is— is it significant enough that a change will make it better? Alright, so watch this— we go to code,
1:53 this is a pretty amazing feature, locate duplicates. Now, if we run this, and we pick the whole project, we could do one file or whatever;
2:04 actually it'll do this for many different types, Javascript, Python, HTML and so on.
2:10 So we're going to use Python, and you can anonymize certain things like look for the same structure but ignore the details
2:18 of say like a string and a number but if you're taking a string and a number to it
2:24 and then doing something else, then it's always the same that sort of series, if I were to check this that would signal as a duplicate.
2:30 So we've got our options set here and we can just go and run it and watch this bam— across this entire project, we have found two sets of duplicates,
2:41 check this out here, let's see if we can make a little more room. If we open this up in Actors, in the Wizard and we can actually jump between them
2:51 so over here, we are in the Dragon, notice there is a little hierarchy which is really sweet, this is kind of new in PyCharm.
2:58 So we're in the Dragon, and in the init we're checking if the level is less than one and in Actors, over in Creature, we have the same thing.
3:08 So this is not the most amazing thing, we're actually doing this exact same test twice, and let me open up the dragon here,
3:17 it turns out, whoever wrote the Dragon class decided they want to check to make sure the level is good
3:22 but they didn't realize this is actually being called here as well, so there's no need for us to call it here
3:27 because this line will already raise this value error, so we can just remove that duplicate, and let's run our find duplicates again.
3:34 Alright, now we're down to this one set of duplicates but there's three of them and notice, I can use these little arrows to change
3:46 like if I want to and do a diff, this one against that one over here, so you can like move these arrows around, pretty cool.
3:51 So it says these are identical, they don't have to be identical, but notice there is this representation that appears multiple times
4:00 and if we just jump to it, you'll see that what we're doing is when you print out a Small Animal it says
4:07 here's a creature of this level and with this name. But the dragon does the same thing and the wizard does the same thing,
4:13 but they all derive from Creature, so what we would like to do is move this sort of just into the Creature
4:21 so we could come down here and the Wizard has the same problem, so let's just focus on the Wizard for a minute.
4:28 So down here, I could hit CRTL T to refactor and I could say pull members up in the hierarchy. So what I'm going to do is I am going to
4:36 automatically move this from the Wizard into the Creature, so it's part of the base class. Hit that— boom, done.
4:45 So it's out of the Wizard, if I look at the Wizard the Wizard just has attack, and now, we have the Creature there init
4:54 defensive role and now they have this representation, and because it's in the base class, and it's the same, the Small Animal doesn't need it,
5:03 and the Dragon doesn't need it explicitly because they all derive from Creature and if we run it, it should still totally work fine, let's see.
5:11 We run it, a level 12 Tiger has appeared, we are going to attack that, a Dragon has appeared,
5:18 so you can see this is the little print, the representation thing, I think somewhere around here, it's showing up.
5:26 But the idea is we can use these duplicate code plus refactoring to improve our code and it's fine on this little example of two files
5:36 but if I had a hundred files, you would see this would be way more valuable because it would make sure the whole thing was hanging together.


Talk Python's Mastodon Michael Kennedy's Mastodon