Refactoring Code Smells0:25
So if I make a mistake here, I'm kind of screwed into making that guess. So we'll add support for that as well. Okay, let's get going. So when I'm refactoring a file, it's mostly a process of scrolling the page like this and waiting for things to jump out at me. For example, long method names jump out at me. Next, long conditionals like this kind of jump out at me. And then right down here, this jumps out at me as well. So in this case, we're on game, but we're telling Tile what to do. So we're sort of micromanaging here.
Let's put that at the top. And now this reads better. When I grab the currentGuess, we reach for the currentRow, and look, it's right above it. Okay. So let's go down here, clean this up. And then next, yeah, while we're here, let's see what we can do here. Like I said, super long method names might be okay, but they're also a smell. And remember, code smells don't immediately mean bad. It just means there's a bit of an odor here.
And remember, code smells don't immediately mean bad. It just means there's a bit of an odor here. Maybe give it a second glance, and maybe you decide it's fine. But also you might decide, hmm, maybe we are missing something here. And I think that might be the case. So in this case, let's quickly go over it. We iterate over the current row, and then we update the tile's status based upon where that tile letter fits into the underlying word. So with that in mind, I said updateStatus, so maybe I can make that a behavior. updateStatus, like that.
Move Status Logic to Tile2:10
So with that in mind, I said updateStatus, so maybe I can make that a behavior. updateStatus, like that. Okay, let's do this in a split. I'll go to tile, and we're going to have a new method here called updateStatus. Or whatever, if you have a better name, like maybe what we're really doing here is validating if the tile is correct. I don't know. But in this case, we are setting the status each time. So yeah, we'll start with this, and then if we come up with a better name, we'll switch over.
All right, cool. So I like this a little better. Now tile is responsible for updating itself, which means if I switch back, we no longer need the index. I could then maybe remove the braces. But you know what? You'll remember up here, where is it? When we fill a tile we use for let of, it'd be kind of nice if I could mimic that. And then I start to see patterns take shape. So let's return this to let tile of currentRow, because I no longer need the index, so
And then I start to see patterns take shape. So let's return this to tile of currentRow, because I no longer need the index, so I don't have to do a foreach. And I can then say, right over here, grab that, and move it in. All right, have a look at that, see what you think. Maybe a little bit cleaner. And then further, I think we can solve this long methodName. The method itself is short enough, maybe we can just move it up here, and get rid of the extracted method. Sometimes I'll do this, sometimes I still want it extracted, it just depends.
Clarify Remaining Guesses6:40
we return. Otherwise, if, and notice right here, it's going to take me a minute to realize what the check is. I can see, is the guessesAllowed equal to the current, so I'm checking to see if there's basically no remaining guesses. But that took me a few seconds. So right off the bat, that's a signal to me, let's give that a name. And we could maybe say remainingGuesses. If remainingGuesses is zero, then the game is over. Notice how that reads better.
This is just a simple explanation with no code.
Return, give me the guesses allowed, and I'm sorry, subtract the current row index, and then subtract one to offset it. Is that right? All right, I want it to say two, yes. And then one, and then zero, okay, that's correct. Yeah, sometimes you just have to see it to get it to work. Okay, so we return early here if they figured out the word, which means I no longer need an else if. I can just bring this down here. Next, if there are no remaining guesses, then we set the message, and then also I set the message.
I can just bring this down here. Next, if there are no remaining guesses, then we set the message, and then also I set the state. But the game is complete whether you lose or you win, but I only update it down here. So maybe we should do it in both places. Update the state of the game, and then return a message. Okay, and then finally, I no longer need an else here because if we hit this point of the method, the else is assumed. So I could do this. And then actually I want to be consistent here, so return like that.
So I could do this. And then actually I want to be consistent here, so return like that. Okay, so now submitGuess is still a little lengthy, but again, it's kind of the workhorse here for the game. So what I like to see is there's not more than one level of indentation, and really it's fairly easy to read. So I'm not too concerned here. Okay, let's go to the top and do one more quick scan. We have some getters. We have the initialization.
We have some getters. We have the initialization. We handle a key press. We fill the tile. We submit the guess. I think this is fine. Really pay—look, we're not even at 74 lines of code. Okay, so I'm ready to continue on. Let's do a quick sanity check. It's all working.
Add Backspace Handling9:40
Let's do a quick sanity check. It's all working. Okay, so now let's handle situations where the user presses the backspace key. So I know that I can listen for that here on the onKeyPress method. So if the user typed a tile, fill the tile. Or if they pressed enter, submit the guess. Or if the key is—and I'm not sure what that key is—delete. I think it's backspace. We'll say alert backspace to check. T-A-C, delete, or backspace.
We'll say alert backspace to check. T-A-C, delete, or backspace. Yeah, so I did hit that key. So now how would we basically unfill a tile? If I type T-A, delete, I want to do the opposite of filling a tile. We want to unfill it. We want to clear it. We want to empty it. Pick a name. Pick a method name.
Pick a name. Pick a method name. You'll remember a couple episodes ago, I think we used the term empty. I want this name to be the opposite of fill. So sometimes what I'll do is Google it. You'd think empty, right? Yep, first one on the list. Okay, that's what I'm going with. So when we empty a tile, we update its underlying letter to an empty string. So would we—here, let's do this.
Implement emptyTile Method10:50
So when we empty a tile, we update its underlying letter to an empty string. So would we—here, let's do this. Create a new method. And this will empty a tile. And we would do that by saying for let tile of the currentRow—how do we want to do this? So we're iterating over each tile, one, two, three. But I want to grab the most recently created one so we can reverse it. Can I do this.currentRow.reverse? Let's see if that works.
Can I do this.currentRow.reverse? Let's see if that works. And then I could say—we're basically doing the opposite of what we have up here. So if there is a letter filled, then tile.empty, and then break. Let's give it a shot. T-A, delete. And no, it didn't work. I think it's how I called reverse. Let's see. Let's do this.
Let's see. Let's do this. this.currentRow.log. Open this up. T-A, delete. And, oh, we don't get anything. Console.log. Oh, I'm sorry. this.emptyTile. Okay.
Fix Reverse Without Mutation12:22
Try that. T-A, delete. And now we get a different output. That's very strange. That didn't work. Or actually, maybe it did, but we are reversing it in memory, and I don't want to do that. I want to basically create a new version and then reverse it. So to do that—okay, I got this. To do that, I'm going to create an array here like this. So this is sort of like cloning it.
To do that, I'm going to create an array here like this. So this is sort of like cloning it. We're creating a brand new array consisting of each of the items from currentRow, and then we reverse that. I think that will do it, and then we don't mess things up. T-A. There we go. Okay. Whew! I was worried I had that wrong.
Okay, so if we come up to our key bindings, again, this is fairly easy to understand. Do we fill the tile? Do we submit the guess? Or do we empty the tile? You know what? I kind of want emptyTile to be up here. So let's do this, else if key is backspace, then empty the tile, and then clear that out. Reformat. Now here's another case where we could return early like we did before, but for some reason I don't mind it in this case.
