Lesson 10 of 11

The Big Refactor

Duration: 1:28:13 Watch on YouTube (external link, opens in new tab)

Markdown version

In this lesson

In session eight the pair refactor before adding a group of three, guided by don't repeat yourself and the single responsibility principle (external link, opens in new tab), since simple code forces thinking about tests. Removal logic moves into a stone remover class with a removal arguments parameter object, leaving the board to manage the stones. The checks become removable detector classes returning lists of position tuples, one looping over checkpoints, and the classes move to their own files and folder.

Transcript

8,491 words

[00:07] (external link, opens in new tab) Hello everyone and welcome to session number eight I think. Isn't it Raymond? >> I think so. >> And how are you dealing with all this? Getting bored? >> No, it's it's getting more exciting every single time. >> Well, that's that's very kind of you to say. So where did we leave leave off last time? >> So last time we added determine

[00:43] (external link, opens in new tab) A group of two surrounding group of two in a vertical position. >> Oh yeah. >> So >> someone said >> we added that we're we're actually digging ourselves into a hole there. So that might be interesting to see how we end up with what kind of algorithm. >> Yeah. Yeah. well I was I was thinking that we might end up refactoring in the end. So >> well we can start refactoring now if you want or we can add some more features.

[01:18] (external link, opens in new tab) Let's see what do we have so far. Are we do we like the code that we have? Let's see. Yeah, >> not crazy about it. Remove stone surrounded is kind of looking weird now, >> right? With the fully surrounded and almost surrounded parts. Yeah. So, we have a like a surrounded on top on to the right.

[01:50] (external link, opens in new tab) That's interesting. >> so this stuff, this code is only for like two stones connected together like like what happens when we add a third stone. So should we that would definitely like change things a lot. So should we refactor before we start adding tests for a group of three or should we add add that and then that would be taken into consideration in refactoring? It's our choice.

[02:21] (external link, opens in new tab) Usually I would say let's refactor first because the code is already kind of ugly >> also. We have two choices. I mean just about that feature. We can either choose to implement almost surrounded to the left or to the to the bottom. >> or go to surrounded by three or more. I mean three or more being surrounded. >> Mhm. So, and based on our choice, our design is going to change as well.

[02:54] (external link, opens in new tab) >> All right. >> So, what do you think? What do you want to do first? >> I think normally if I was to do this on my own, I probably want to consider refactoring. At least in the position where our code is right now, I feel it's really hard to I feel it'll be a lot of work to add in another test for surrounding a group of three with the code we have right now. >> Sure. >> So, >> okay. So, how do you want to refactor this?

[03:26] (external link, opens in new tab) Do you have any interesting ideas? So I I just find it interesting in the first place that we have and is fully surrounded by and almost fully surrounded by. >> Okay. >> >> and they're kind of themselves, >> right? >> Okay. So, >> so the thing is like you know how like I implemented this before, right?

[03:57] (external link, opens in new tab) So the way I did it though, I'm worried that sometimes that the way I did it before might affect like the test that we write or like maybe just I might end up just jumping into it and skipping the whole TDD (external link, opens in new tab) process because the so the way I implemented it was that I would get all the stones and then get all the and all the stones that connected and then get the positions that are adjacent to the stones and check that they're all filled with white.

[04:39] (external link, opens in new tab) >> Okay. I I don't understand how is that happening in terms of design though. >> I mean like right now I I'm worried that it doesn't I mean it's totally different from what the way we're doing it right now. And I'm worried that it's not like driven by tests. >> Mhm. Okay. So >> So is that is that a problem? >> Well, I'm trying to understand is it a problem on on your own different implementation?

[05:10] (external link, opens in new tab) Is that what you're asking? >> Yeah, like switching from one implementation here to another implementation. Well, it wouldn't be a big problem, but my guess is that the possible risk here is that there would be some features that aren't being tested that already exist there. So, there would be it would be more generic than this code >> and so we would have less of a inclination to write any tests for it, >> right? I see. >> Okay. >> Okay. I mean we could switch it all and then some these things will actually work but then we won't know which features actually exist.

[05:46] (external link, opens in new tab) We will have to like guess which test we want to write. And in in real life usually if you do it like that you just say okay well it actually works really nice. I can't think of a failing test for this and that's it. >> And the whole point here is that you're not objective. We are not objective when we write the code. So >> by writing it as simply as possible, we're forcing ourselves to also think about the tests. >> Okay. >> So if we implement everything, we're not forcing ourselves to think about the test and we're basically saying, yeah, well tests are not as important for this.

[06:23] (external link, opens in new tab) It doesn't have to be covered in in terms of functionality. It just has to have some tests, >> right? >> And I want every character, every line in the code to have a reason to live >> basically. >> Okay. Now in terms of possible refactorings there are two kinds of rules that I always look to and one is don't repeat yourself >> and the other is the single responsibility principle (external link, opens in new tab) >> right >> okay so that every method has one reason to change not two not three

[06:57] (external link, opens in new tab) >> so in terms of refactoring I I I think there's plenty that we can do here >> right >> I mean if I look I look at the code. Remove stone is surrounded. I mean, this thing here, I mean, if you look at this, this is actually setting two stones. It's actually setting stones to empty, right? >> Right. >> So, and this the same here.

[07:28] (external link, opens in new tab) >> Mhm. So what if just as a as a as a start measure I will refactor and say remove stone with XY. >> Okay. It's the same here.

[08:02] (external link, opens in new tab) >> It's almost the same here, >> right? But x + one and here it's xy and xy minus one, >> right?

[08:38] (external link, opens in new tab) Cool. Now when I do that, I see that I have removed stone. I don't have to repeat this three times, >> right? >> That makes sense. >> Uhhuh. >> I mean, it almost looks like I have to remove it if it's fully surrounded. >> Right. I see. >> So, you want to make one conditional statement for that? >> What? I I was just wondering how you're going to make it not repeated. >> Well, I don't have a magic formula.

[09:11] (external link, opens in new tab) I'm just I'm just thinking out loud about how I might do that. >> Okay. >> Basically, I don't want to if I'm repeating myself here, maybe there's a way I don't have to do it. Mhm. >> Maybe there's a way. I always remove the current stone and I possibly also remove a stone next to it, >> right?

[09:41] (external link, opens in new tab) What would you like say about if you move this this line out and then you put like these a copy of these? I it would be another duplication but it' be a duplication inside the conditional. >> So you would send them as delegates. >> I I don't follow you mean send it as delegates. >> So you would send them as as a boolean parameter or as or as action delegates to be invoked at the method.

[10:18] (external link, opens in new tab) I meant I meant like copying this into >> like a remove stone if >> if or but that would be like duplicating the conditional. >> Oh, I thought you meant call remove stone with the conditional. >> What do you mean by call stone with the conditional? Remove stone.

[10:48] (external link, opens in new tab) This >> Oh, I see. >> Like a remove stone if Let's see. So, let's think about this logic for a second. Okay.

[11:19] (external link, opens in new tab) Remove stone surrounded. Rem we remove it. If it's fully surrounded, remove it. Oh, so that's interesting. So, so the way I think about it now is that we do have an interesting refactoring we can do here. So, remember when we had strategies that didn't make sense for detecting that something >> should be for detecting a winner. >> Mhm. >> Because there's only one way to detect a winner, I guess. But here >> we might have strategies to remove stones.

[11:52] (external link, opens in new tab) >> I see. >> First one is remove a fully surrounded strategy. Second one is surrounded on right strategy and this one surrounded on top strategy like a removal like a chain removal strategy or something like that. And that way we don't have to have the if we would basically have like either a base class or something like that that basically does the checking and has like a strategy for detecting all the different things.

[12:24] (external link, opens in new tab) Okay. >> Does that make sense? >> It makes sense. But the thing is that if this is a separate strategy and this is a se separate strategy, >> the almost surrounded is going to be calculated twice. Is that going to be fine? >> Well, we don't care about performance yet. >> Okay. >> Remember, we h it has to work and then we can optimize. So we want to reduce duplication in code first and then duplication in like performance-wise

[13:00] (external link, opens in new tab) Is secondary for now. >> Yeah, later we can optimize the hell out of it. But it has to work. >> I mean it has to be maintainable and when when that works we should hopefully have only one place to change it. >> Maybe somewhere in the base class or something like that because you you won't have to have that duplication. you might have the like the checking almost surrounded in the base class or somewhere. >> Okay, >> so here's an example. We can start the refactoring by saying

[13:30] (external link, opens in new tab) Stone remover equals new stone. Okay. >> Okay. X and Y and it takes in the rules and the board. Actually that that that already is too many parameters. So I would actually call it directly with a like with a parameter object like u new removal arguments

[14:05] (external link, opens in new tab) That has these properties. So we would have like x = x y = y. The rules, right? Rules rules and board equals board.

[14:36] (external link, opens in new tab) It's inside the board class. So this >> Yeah. >> so new removal of the thing. You have a extra >> is this right? >> Parentheses like right here.

[15:08] (external link, opens in new tab) >> okay. Let me just finish that. Did I miss anything? >> I don't think so. I think I think you got it. Oh, you're missing a comma right here. >> Okay, put it. Cool. So if we had the stone remover class, first thing is we would put all this into that stone remover class. >> Okay. And then we would refactor to different strategies.

[15:39] (external link, opens in new tab) >> Okay. >> Otherwise the board knows too much already. >> But we going to go ahead and say create a stone remover.

[16:20] (external link, opens in new tab) Just basically go ahead and create all these properties.

[16:56] (external link, opens in new tab) And bor. Yeah. >> Something is more accessible than the other. Let's see. Maybe rules class is not public. >> Sure. Cool. So now let's see where

[17:33] (external link, opens in new tab) So now basically I would go and say remove horrible. >> What are you typing on? Probably something that's not a keyboard. It's like a Schwarzenegger was typing. >> Yeah. >> Then we would have all this

[18:05] (external link, opens in new tab) And our first thing is to get rid of rid of all that logic. >> Can you refactor and put that all that there? I think that it'll be faster. So take all this >> Yeah. and put it in the remove method which doesn't exist yet. >> And put it in in stone remover. >> Yeah. In the remove method which we have to Yeah. to generate. >> But what be the best way to generate is like this. >> Yeah. Exactly. >> Tab tab.

[18:42] (external link, opens in new tab) What the hell? Nope, that's not what we meant. Now we Okay, now now if you Okay, try to paste it. See what happens. Yeah, we also need to remove stone. Forgot about that. >> >> it's still in the board. >> Oh, it's still in the board. I see. So move this out.

[19:26] (external link, opens in new tab) >> Yeah, just import it. >> Alt enter. >> Yeah, but the remove stone method is still on board. >> That's why it's saying that it doesn't There's a method called remove stone. It's just like >> you passed it. >> You're talking about this. >> Yeah. >> You're talking about this method to remove >> stone. We It's still on the board class. >> Yeah.

[19:56] (external link, opens in new tab) So, you don't want it inside the board class. Do you want to take it out? >> Yeah. Because it's it's >> or we can make it public. >> We would say board. I see Nick. I don't think I don't think there's anything wrong with board. >> Except that we have a class that the whole point of it is to Oh, because it needs access to the stone matrix. Right. >> Right.

[20:27] (external link, opens in new tab) >> Public. Cool. And so we just have to >> What was your issue with having a remove stone in the board that you had or has that has to access another class? >> Yeah, I mean it's a stone remover, but that's okay. I forgot that it needs access to the board matrix, >> right? You're mistyping everywhere. So this is saying you treating as a static I mean we had to create a property for board right now >> we should already have one oh oh it's args.board actually

[21:04] (external link, opens in new tab) Right so we have to save it or we can if it's it can't be static right >> right >> yeah so we just have to have a property called board that we can or args.propy property called board, >> right? >> Introduce initialize args. >> Nice. >> And then we can say args board. >> Okay, I can type it for you. >> Okay.

[21:51] (external link, opens in new tab) Okay. >> yeah, but remove takes an X and Y. No, >> I see. >> No, it doesn't. >> Yeah, I thought I thought it So, it didn't Oh, so no, the you define X and Y in the remover. Okay, so you're talking about args.xy, >> you know. But you know what we could do is just to make things much easier instead of replacing rxy everywhere >> right >> is we can do

[22:25] (external link, opens in new tab) >> well what happened there's ghosting >> okay but what if we just did like this yeah I can definitely see the ghosting here That's a disgusting thing in viewer. >> Maybe it's better if I Oh, actually I do it right now.

[22:57] (external link, opens in new tab) >> There we go. >> Okay, it's cool. >> What if we just did this? Then we'll just say remove args x.

[23:33] (external link, opens in new tab) >> Okay. But what about the rules object? Do you want to define that as a parameter too? >> Well, we can use rx.ruules. It's easier. >> Okay. >> We can make this non-public if we really wanted to. >> okay, >> I've gone ahead and copied this for you so you can do your thing. >> All right.

[24:16] (external link, opens in new tab) Okay, we're back to green. That's good. So, we're doing it slowly but surely. So, now at least the board and the remover are in different places. >> So, the removal logic, which is getting quite out out of hand, is at least we can at least it's it's clearer. So if we look at the board back here, stone added, check around and remove if needed. That's the rules, right? >> Right. >> That's interesting.

[24:48] (external link, opens in new tab) The board has rules. The rules call check and the rules call them later to the board itself. remove stone if it and then the board calls stone remover. >> So we can make that nicer as well. We can go ahead and just maybe maybe the logic that goes through each one be different. I'm not sure. I mean there is kind of like a weird

[25:19] (external link, opens in new tab) Path. See what I mean? >> Yeah. Can you go back to why why does the rules why does the board calls rules again? >> Well, we used to have a we have a method called check stone around position and remove >> which does this. So, this is the only reason because we wanted to have an algorithm just looks around >> the thing that was just added.

[25:50] (external link, opens in new tab) >> Right. Right. Instead of instead of calling board the rules can actually create a new remover for each one and be done with it. >> That Yeah, >> that's what the board does anyway. >> Right. Well, wait.

[26:20] (external link, opens in new tab) What does remove stone is do now? It's >> go to it and see >> where is it? >> I mean, we can just extract this method and put it and be done with it. >> You're right. You're right. Because it it doesn't do anything straight from the board. You're right. Go ahead and say

[27:28] (external link, opens in new tab) Yay. Nice. Much cleaner. That's quite amazing how that worked out. So because we extracted it into another method. >> So >> pretty nice. >> We still have some work to do. But the point is that now the board has a single responsibility and that is simply to manage the stones. >> Right? >> Else it has the rules and the rules decide what to do when a stone is added.

[28:01] (external link, opens in new tab) >> We has a remover. We I can has a remover that removes things. >> Mhm. So now we can make removal strategies here maybe >> right. >> So and again slowly but surely will work. So basically we can say like we can do all this right now as a method and say

[28:32] (external link, opens in new tab) Remove My fully surrounded strategy. And then we would have this move by

[29:03] (external link, opens in new tab) Right chain. >> we call it >> remove if almost surrounded except to the right. That's pretty long. We move to the right >> maybe. >>

[29:35] (external link, opens in new tab) >> oh, it's turns and almost surrounded. That's interesting. Did I miss something? Did I >> I think you might It might have been when you selected the whole thing, you thought you were trying to return >> a parameter or something like that. So if you try control controlm or alt r and r enter is it alt enter.

[30:05] (external link, opens in new tab) >> What are you trying to do? >> Control alt m to refactor. >> Oh alt. What the heck is going on? >> Control alt m >> or control alt m. Okay. I think it's because you it selected a return value right here. So you wanted void, right?

[30:35] (external link, opens in new tab) >> No, the the the the problem is that we have an if here that uses something. >> Oh, it uses the same almost surrounded, right? Yeah. >> So if we did that instead, we would say So we're on top too, >> right?

[31:06] (external link, opens in new tab) >> The strategy separate. >> Okay, I see. >> Wait. Let's call it removed if chain on right surrounded or if >> it's still going to return something. >> No, it says return void. >> Yeah, >> remove what? What would you you put in the name? >> All right.

[32:03] (external link, opens in new tab) And I like how we're getting the feedback without running the test that we we didn't break anything. >> Yeah, it's very nice. Cool. And now we can go ahead and for each one create like a strategy for it and then later we can even remove the calls to the methods.

[32:35] (external link, opens in new tab) Another po another thing we can do is just keep it this way. Okay. >> What do you think? >> I' I don't understand the other way though. I understand keeping this way. I don't understand creating a class and the one the other way you mentioned. >> Okay. So, it's almost as if we did the the get winner strategy. >> Mhm. >> But as a removal. So we would say fully surrounded strategy.

[33:08] (external link, opens in new tab) Okay. So we would have like a strategy. What if instead of strategy would have like a detector that tells you what to remove instead of removing it, right? Because we have a class that removes things.

[33:38] (external link, opens in new tab) So it would be like removable detector or something. >> Sure. >> Removable. >> Let's go with that

[34:12] (external link, opens in new tab) Fully surrounded detector equals new fully surrounded removable detector. Okay. Now the way it would work is that we would say fully surrounded room detector detect for the board would have like an args.

[34:44] (external link, opens in new tab) Okay. >> Okay. And what it would return is like what we need is basically an array of XY positions to remove. >> Okay. All right. >> So how would you declare that >> and so pairs basically an array of pairs. >> well >> I don't know another way. >> Okay. >> Except this one.

[35:14] (external link, opens in new tab) No problem. Results. Okay. It doesn't make Oh, alt enter to add the list. And alt enter again. Cool. And then basically is this one supposed to be is this one supposed to be this this value? >> Yeah. Okay. And then we would basically

[35:48] (external link, opens in new tab) Do like a results each. This be the same line as this thing. >> Yes. >> Or do stone as to pull

[36:20] (external link, opens in new tab) >> item one and tuple item two. That's that's what we're going to get. >> Yeah. But that's basically what I'm thinking. >> Okay. >> And that basically each one of those detectors might return multiple things. >> Mhm. don't care. >> So, is that thinking too far ahead? >> Well, we're already trying to make it a bit more general in that

[36:53] (external link, opens in new tab) Is it too far ahead? Do you think it just should return a tuple and that's it? >> Sure, we can make it just a tuple >> just for now. And >> Sure. Sure. I like I like the way you think. We don't have to do it. We don't have to do it. >> I'm just saying like I'm just wondering

[37:30] (external link, opens in new tab) Need to do a check if >> the null. Sorry. >> Would you need to do a check if the tuple is null? Like if the >> No, now you're Now you're thinking ahead. >> Now I'm thinking too far ahead. All right. >> Okay. So, basically, we're going to have this in the removal detector. Can you Can you make that?

[38:01] (external link, opens in new tab) >> Yes. Oh >> yeah, sure. No problem. We can move it later. >> Okay. >> Actually, yeah, we have to call it a fully surrounded removable detector. >> Well, that >> that inherits from a removable detector, >> right? So, just I'll enter this one, right? >> Sure.

[38:33] (external link, opens in new tab) And then we have a detect which is like an abstract method. >> it's abstract. This method has to be abstract. >> Okay. Do I need >> it has to be public too? public abstract.

[39:16] (external link, opens in new tab) >> Is that is that not right? >> And I think it has to be an abstract class as well. >> Sorry. Okay. >> And now this class has to Oh, it's not override. Just Well, you're working too hard. You see that red line there? Just press alt enter. >> Alt enter. >> Yep. It's always alt enter. >> All right.

[40:05] (external link, opens in new tab) It's basically the same logic in a different place, >> right? >> Except instead of removing it should be >> just returning just return the tuple of x and y, right? Oops. Yeah. If

[40:41] (external link, opens in new tab) Oh, >> it's rx.x. Where the hell did the opposite color come from?

[41:11] (external link, opens in new tab) Should we put in the opposite color inside here? >> Sorry. >> We add opposite opposite color to detect as a parameter. Interesting question. Where is the opposite color coming from? >> It's coming from before we had it right here and it was from remove fully surrounded strategy and it's that is from right here in the remove. >> I think it's just board.get opposite color or is it rules? You can just get it from rules.

[41:42] (external link, opens in new tab) >> Okay. Okay. >> >> Just want to do it in equals.

[42:38] (external link, opens in new tab) Mobile. >> Everything's broken. >> So, I'm guessing Hold on. Let's make sure. >> Okay. So, now we know at least that it's all in the new code.

[43:09] (external link, opens in new tab) Well, I think if we look at the error code, it's going to say >> actually you'll see this code never gets executed. >> It's right. >> No reference, right? So, if I add in a line right here. >> Oh, yeah. We have just have to check. Yep. >> Oops. >> Yeah, if you added a line right. Well, I was that if to

[43:41] (external link, opens in new tab) Not know. >> Yeah, I think you can do if you hold on. Well, yeah, that fixes it. But I'm just saying I think you can do like this. If you go on tuple, you should be able to say check if it's not multi. >> Very cool. >> Okay. >> Okay. Now we can remove this.

[44:23] (external link, opens in new tab) >> Okay. So now we have a class that knows how to detect like a single stone. Okay. >> Okay. Okay. So, basically the process would be to go ahead and create and each one of them will be strategy. The one that looks to the right, the one that looks to the left. >> Mhm. >> Now, what's cool about this is that then we can later do one that looks multiple places and it won't hurt all the others because they'll just return a list that doesn't contain X and Y if we already remove them, >> right?

[44:56] (external link, opens in new tab) Right. >> Actually, that might be a problem because if we already removed something that's fully contained. >> Well, right now we're only using Well, actually, the code doesn't prevent it from using multiple strategies right now. >> Yeah. But we we I think when we get to three, we're going to get there and then we'll say the first one that that works is the one we're going to use. >> Mhm.

[45:27] (external link, opens in new tab) Okay. >> Otherwise, they might collide with each other at some point. >> Mhm. >> Okay. So, you want to do the other ones as well, or do you think that the strategy of one to each position is one strategy? >> Strategy one to each position. >> I mean, one to the right, one to the top. >> Oh, that's a good point. I think that is one strategy that the I Well, is that generalizing it too much?

[45:59] (external link, opens in new tab) No, I don't think it's generalizing too much. >> Well, we can try it. We can always refactor it later. >> Okay, let's try it. Let's You mean like try putting it as one strategy, right? >> Oh, by the way, have you noticed we don't need these arguments anymore? >> Right. Look at this. We can say that. We don't have to We'll say

[46:55] (external link, opens in new tab) Okay, sorry. So now you what what I'm thinking is that let's see is that all these three are just a single strategy but it's possible that each one of them is a different one. So it's a single strategy that that's only partially working. I mean, yeah, not all three. I'm sorry. Just the bottom two, >> right? All right. Okay.

[47:28] (external link, opens in new tab) >> But each one of them can be its own strategy as well. So, whatever you think makes sense. >> I I would I would like to do the single strategy or or a different version of a single strategy. >> Okay. You want to try and do it? >> All right. So,

[47:59] (external link, opens in new tab) So the first thing I would need to do is change one of these to look like this, right? chain. >> Sure.

[48:30] (external link, opens in new tab) >> With neighbor. No, chain. >> Well, by chain makes sense to me. >> Okay. By chain. Stranded strategy. Oh, detect your surround. >> Sounds like your left is out of batteries. >> How's that possible?

[49:15] (external link, opens in new tab) >> >> Solves. >> Well, remember this one does not return a single one. It returns a list. >> All right. Okay. Well, right now the way we have it. Oh, yeah. You're right. It returns two.

[49:46] (external link, opens in new tab) You're right. You're right. I see. I see where you're going. I see where you're going with that. Okay. You're clever. So, because of that, I have to How would I do that change then? just just do the change as if everything's great and then make it compile because like well I guess it would make another detect

[50:21] (external link, opens in new tab) Because then right now this detect is only returning a two but well like one is not returning a list. >> Yeah. >> Okay. But I think it will just force us to make the abstract return a list. But it will the previous one will just have one in the list and that's it. >> Results dot I like your for each use of list link. >> Now you can do control shift enter control shift space. Sorry. >> Okay.

[50:51] (external link, opens in new tab) Is it this one? I see. Okay. And then what are you doing?

[51:27] (external link, opens in new tab) Okay. So, what does this say? Change results. Replace change type of results. >> No, no, no. You have to change it to the abstract method level. >> I was I was wondering if it had if ReSharper was able to do that for me. >> Maybe Maybe it did. Maybe I missed it. >> No, it didn't look like it it did.

[51:58] (external link, opens in new tab) So, this one. This one >> just used Hold on. Instead, what you could have done is just tuple equals detect dot first. >> Ah, >> wait. There's probably a link missing.

[52:31] (external link, opens in new tab) If you go to >> Yeah. System.Linq. I think it's a parenthesis. There you go. >> Okay. >> So, let's make the other one work. >> New list. Right. >> Right.

[53:21] (external link, opens in new tab) >> Okay, cool. Oh, something's stilling to build. Oh, it's because I don't have this one yet. That might be important. >> Say again. >> Yeah, that one might be important.

[53:51] (external link, opens in new tab) >> so basically this copy this. >> Yep. What just happened? >> Tab. Tab happened.

[54:25] (external link, opens in new tab) You want to do the X and Y like you did before? I I did this part enterable

[54:58] (external link, opens in new tab) And then >> still not compiling. >> Well, it's this part because I didn't I didn't return the return the list yet. Oh, >> so Well, you know you have exactly two right now, right? >> Right. >> Then you don't have to like declare you just create a new list with the two in there. >> Right. If >> So you're talking about return it right here.

[55:31] (external link, opens in new tab) >> Right. >> Mhm. >> Okay. Oh, how come it's like that? Okay. Is that right? >> No. No. It's a new list with an array. Remember, it's an array of neutrals. Hold on. >> Oh, okay. I I know what you're talking about. >> Okay. Do it. Wait. You're talking about this, right?

[56:02] (external link, opens in new tab) >> No. Yes. Yes. Yes. >> Yep. >> Okay. >> And then >> just return null. >> That didn't work. I guess you have to return. >> I think it's the it's the checking if it's null first. This one is no exception value cannot be null.

[56:35] (external link, opens in new tab) So this one still checking it's null. >> >> oh yeah true >> because he's calling first. >> Ah yeah I agree. >> So we can't return null in the in the strategy. We just have to declare it nicely. Just return an empty list. Ah, okay. >> Right. >> Oops. Sorry. You want me to do it?

[57:06] (external link, opens in new tab) >> No, you do it. I think it will be faster. >> Okay. Like that. All right. >> Yep. >> And then this one, too. Ah, what? Something's still not wrong. Still, what's this? What's wrong when running? Oh, okay. I guess can't work. >> Contains no elements. >> Oh crap.

[57:42] (external link, opens in new tab) >> Yeah. So we have to do it the stupid way. Get the list. See if the list is empty. Blah blah blah. God damn it. Can C# just help me out? But the list does not have any items, sir. I don't know what to do. >> Is there like a first or default? >> Yeah, >> which is better. >> >> Oh, that's better.

[58:14] (external link, opens in new tab) >> That works. Cool. >> Okay. And in that case can go ahead and just do we want to copy these two lines to here now. Now that's working. >> I don't understand what do these where do they come from? >> From the remove chain on right.

[58:51] (external link, opens in new tab) We have remove chain right >> because right now it's returning we're doing the first or default. >> Sure. It doesn't work. It's not the same. >> I mean if I >> but you know what we can do is we can just have like a method that goes through a list of tuples and that's it, right? like here. >> Isn't that what what it did?

[59:23] (external link, opens in new tab) >> No, what I'm saying is that this would be like a remove all items. >> Okay. I think you deleted the one the line that you just entered.

[59:53] (external link, opens in new tab) >> H >> you just deleted the line that you entered. >> That's stupid. All right. So I just moved that. Now, how to make it more generic? >> What do you mean more generic? >> Well, we were trying to combine this one with this one, right? To use one detector. >> Well,

[1:00:24] (external link, opens in new tab) We don't have to have the second method call. That's the point. If we remove the second method call, then the first one should just work if we add that functionality to the to the thing. Do you I I don't think I understand why second method call. >> So >> we have this one right agree. >> So now if we didn't call this one at all but we just took the logic here and put it in the same strategy

[1:00:56] (external link, opens in new tab) And make it return more results or different results. >> I see. >> Then it will work and then we can refactor the current strategy to make it more generic. Okay. >> So we remove something then we check and then we and then so it's small steps. >> I see. So what so what should I do right? So we should move that into the chain removal detector. >> Well first of all I would remove the call to the method you're in right now. So it would force me to put the logic that it has inside

[1:01:29] (external link, opens in new tab) The strategy of the chain. I would just you know right on the method right here I would say let's not do that anymore. >> Okay. >> Right. So this method becomes ray I say okay >> if I didn't call it anymore and I wanted it to be in the strategy in the removal I would just go here and find a nice place to add that logic. >> I see. >> And when they both work together >> I would refactor again to make it more generic.

[1:02:01] (external link, opens in new tab) Okay. >> So, I already copied it. Where do you want to add this? >> it would be the same right here. So, the difference would be >> Okay, that's good. >> This would be This one would be back to one. >> Mhm.

[1:02:32] (external link, opens in new tab) Okay, that's good. So now everything's passing again. >> So we can remove the call to the other method, right? We just put it in a comment where we can remove that method al together. >> Right. >> So get rid of this. Ctrl L and then get rid of this. >> Yeah.

[1:03:06] (external link, opens in new tab) Now, now we can go to the strategy and refactor it again, >> right? >> So now it's possible that the strategy has multiple ifs because it is a strategy that looks for different places. But we can make those ifs a bit more generic. Like for example, >> given an X and a Y. Okay. Like if we had a list of tuple pulp, sorry. >> Mhm.

[1:03:38] (external link, opens in new tab) >> Of in >> Yeah, of course. >> I'll fix it for you. Sorry. >> Do not dare. >> All right. >> to check equals get checkpoints for X and Y. Now the checkpoints right now we only have two

[1:04:09] (external link, opens in new tab) >> correct. Oh, >> collaboration through committee. >> So instead of surrounded on right here, we're checking the x + one, right? >> Mhm. >> And here we're checking the y minus one. >> Agreed. So imagine that we had a loop that that takes like a list of checkpoints.

[1:04:43] (external link, opens in new tab) Given x we would get x + one y minus one like a tuple of of this a tuple of this >> and and right now it would just be these two tuples so that the we don't add new behavior >> right >> but then it will just work as a simple loop for each one of those so surrounded and surrounded on that tool see what I mean >> okay right >> do you see what I'm getting at >> I I see what you're getting at it it definitely looked It looks a lot cleaner now.

[1:05:14] (external link, opens in new tab) >> Okay. So if you do so you want to try and get say say say say say say say say say say say say say say say say say say say say say say implement get checkpoints for x and y >> just return the hard-coded values or something. No, no, array. Forgot the notation there. >> Yeah, sorry to do that.

[1:05:44] (external link, opens in new tab) But >> x. >> So we have x + one and y x and yus one. >> yus. Oops. And just to make it a bit more clean,

[1:06:21] (external link, opens in new tab) Sorry, that's what I meant. Now we have the list. Now, let's turn this into a loop. I mean, basically, we have the the the opposite color, right? So basically what we're trying to do is to turn this into something

[1:06:55] (external link, opens in new tab) Of a loop right here, right? for each >> like to check dot for each. >> You want to try and and do that >> right? >> control shift space >> control. >> No. >> So for each tuple we're doing basically the same check, right? Actually here's something that will be I think this will be more readable.

[1:07:28] (external link, opens in new tab) We make it a delegate. >> Okay. >> So it looks more like a method. Just >> sorry. >> Okay. >> You do it. I'm not going to touch anything. That's what you said. with the Okay, that's fine.

[1:08:10] (external link, opens in new tab) So, we don't have to check on right. We just have to use the tuple xy. Remember >> tuple xy >> here in the x + one >> okay. Right. >> And the Aha. I see what I I see what the problem is. >> No, actually, no. X plus one is good and Y is good. No, no problem there. We're always checking XY

[1:08:41] (external link, opens in new tab) >> and X + one and Y, etc. We're always checking the current one and the one next to it. Right. Right. >> Okay. >> >> so we have to replace the x+ one with what we got from the tuple. Right? The tuple already contains x+1. >> So it returns a tuple.x too, right? >> Exactly.

[1:09:25] (external link, opens in new tab) This thing return type is void. It's supposed to add it to list in the return. So sorry.

[1:10:43] (external link, opens in new tab) Holy crap. Look at that. >> Passing already. >> Yes. You likey? >> I like I like. >> Yeah. Much better. >> Now we can easily check for the other items and just add a very simple algorithm here. Just return a new tuple to check. >> Right. Well, like we we did we did check the other ones like if you remember we did it this way and fortunately >> Oh, I forgot about that.

[1:11:16] (external link, opens in new tab) Cool. >> Yeah. Unfortunately, the reason why it works is because we're checking diagonally. If you remember where right here we checking diagonally and that that worked for it. >> Sure. >> That made everything work. >> So >> let's remove all the comments from there and commit. >> Okay. Let me

[1:11:47] (external link, opens in new tab) >> you want to outline? Oh, okay. >> So that It might be better to say, oh yeah, but you want to delegate and you return the new results. I mean, it might be better to actually even refract that to a method instead. I'm not sure. >> right now I I think it's pretty clear right here. So, >> okay. But I will rename this to >> right right here.

[1:12:19] (external link, opens in new tab) Ah >> actually no one to check to to like check for each and we have a tuple. So the tuple is item next to current. >> Ah >> what position next to current? >> Yeah. You know what it should be like?

[1:12:49] (external link, opens in new tab) Nobody knows what item one is. We can say >> you want to make >> so you want to make an object for it or something >> like in x next I see >> to me the same with y y next to me or something like that I'm not sure

[1:13:20] (external link, opens in new tab) >> and that say we would say, look at that. It's almost surrounded to the right. It's actually not surrounded to the right anymore. It's almost surrounded to some position. Right. >> Right. >> Something like that. I'm not sure. >> Args rules is surrounded X next to me and Y next to me. Cool. >> Mhm. We so the interesting thing is

[1:13:54] (external link, opens in new tab) We probably move is almost fully surrounded into this strategy right and the same thing with the fully surrounded by because if I look at this where's all the find usages >> just control Victory these are the usages is >> I thought you meant to go to the code >> oh

[1:14:26] (external link, opens in new tab) I meant the usage like it's only used inside >> here >> ahu >> so like >> sure >> if I control B and then I move >> look at that >> it's actually Scary. >> Yeah. >> I guess that's our next thing.

[1:14:56] (external link, opens in new tab) >> Where Where did Where did I go? >> You put it on the base class. Maybe. >> Oh, you put in a base class. >> Maybe. >> Actually, that's the only class that's using. It's a don't. >> Yeah. That's that's what I was thinking. Edge. Why can't I resolve edge? >> It's part of board, I guess.

[1:15:30] (external link, opens in new tab) >> it's part of board, right? >> So, >> so >> I think so. Well, if you go to the original implementation, you can see where edge is coming from. >> Where was Oh, it's part of the rules. We made it part of rules. Okay. >> So, rules.edge.

[1:16:01] (external link, opens in new tab) >> So, well, it's going to be args.ruules. Right. Args. >> And I think it's a con, so it shouldn't be a problem. Try rules. edge and see what happens. Ah, okay. It's a >> because it's const. >> I see. Okay. >> Oh dear. Actually, you know what? Hold on, hold on, hold on. Instead of doing all that work, >> just declare edge and use it and just before that line.

[1:16:34] (external link, opens in new tab) >> Oh, okay. Like an int edge equals the rules edge or something, >> right? Very nice. >> And now we have the board get stone color and that needs to change as well. >> Yeah. >> So we have args.board. >> Well, we can always do the same thing here. Board.board equals args

[1:17:11] (external link, opens in new tab) Do we have have access to args? >> Oh, >> yeah. It's on it's in the base class. >> You put it as a field. You should have it. >> Okay. >> It's underscore. >> Well, it's like detect you pass the value args. So, it's not a property inside the class. >> Okay. So, you can move it to this method as an args. I can put it in the class. >> could show me also like how would I do it?

[1:17:42] (external link, opens in new tab) Control al control. >> What do you want to do? >> You said you want to move it as a property of the class, right? >> control shift r in produce field. >> Okay. >> And now it's setting the field. And that's it. Okay. Okay. So that's so this would be args dot

[1:18:13] (external link, opens in new tab) Board. >> Oh just as the first one. Yeah. >> Yeah. And then what's not what's not running? Oh, cuz so then this one would be delete and delete. >> Nice. >> Same thing can be done with the fully surrounded one too.

[1:19:05] (external link, opens in new tab) So since Oh yeah, since we did we could have done this inside. >> How is take small steps? Small steps. >> Okay, >> don't change too many things at once. Make sure that you Crl P. Is there control P or Crl F? >> What are you trying to do? >> Move. Do the same thing with this. >> Yeah, this field >> or in line >> field. >> control shift R will give you the you want. >> Okay.

[1:19:47] (external link, opens in new tab) Just copy. Wouldn't that all this make the the current class build a bit too big? >> The current class. >> Yeah. >> You mean this class? >> >> never mind. Fully surrounded. I mean, now this class and the partially surrounded class. Oh, actually what you're saying is that look, this one only needs the fully surrounded. The other only needs the partially surrounded by. Right. >> Right. Right. So I felt like that was with a single responsibility.

[1:20:18] (external link, opens in new tab) >> It goes well. >> I like it. Nice. >> what's interesting is that well first let's commit so that we don't lose this stuff. >> All right. All right. it had a status. >> I thought I I can git ignore for that. >> Do you want to move the classes to different classes >> now?

[1:20:48] (external link, opens in new tab) >> Right now, >> I want to keep this all in the same file. >> I think I think it's got big enough where we could move it to a different >> Okay. >> Yeah. >> So, let's do that. >> Do that first. Sure. >> Okay. Is there easy way to >> just F6? >> Just put F6 on the class name. >> Oh, F6 on a class name.

[1:21:24] (external link, opens in new tab) And then you wanted to probably move this to another folder, right? >> No, no, no. Don't don't worry about it for now. Let's just F6 for the others as well. Six. >> Yep. Okay. >> Oh, strong. >> It looks like a class. I agree. >> Yeah. >> Okay. >> What about the removable detector?

[1:21:56] (external link, opens in new tab) Okay. Another one. Pretty sure we're not done yet. I think. >> Go back to board. Let's see. Is that all we have now? >> We got a stone. >> We have a stone remover. >> Okay, do that as well. Cool. Nice. And the removal args. >> Removal args as well. >> Okay.

[1:22:31] (external link, opens in new tab) >> Okay. Okay, now let's look at board. >> So you got the class board and we have the rules. Do we want one rules? >> Yeah. >> Okay. So board should only have boards now. >> Nice. Okay. And we didn't break anything, right? >> Yep. >> You want to run the test just to make sure?

[1:23:06] (external link, opens in new tab) Yes. >> so here's what I'm going to do now. Oh, correct. That's not what I meant. Well, we'll talk about that later. What I wanted is to now we can look at this. We have the we have the strategies, we have the board. So we can create like a folder or a new solution folder. >> it's under add. >> Oh actually it's project.

[1:23:42] (external link, opens in new tab) >> Yeah. Add. Pausing for a second. Okay. So, what I'm going to do is I'm going to move like a new folder. Let's rename it to like removable removals or something. >> Remove removal detector. Or do you want to just >> Yeah, we can go removal detectors as well.

[1:24:14] (external link, opens in new tab) I mean, I was assuming that you're making a folder for the removal strategies. >> True. >> So, chain removal surrounded detector args stone remover.

[1:24:48] (external link, opens in new tab) What do you think? >> I think removal is doesn't have a e after it. >> Oh, yeah. Sorry. >> And then everything else looks good. Yeah. >> Okay. Commit the thing.

[1:25:28] (external link, opens in new tab) >> what should I call it? >> The big refactoring of 2012. >> What we say? >> The big refactor of 2012. Sure. >> Actually, we should call it basically removal strategies or something like that. Refactoring to removal strategies.

[1:26:01] (external link, opens in new tab) >> Cool. >> Yeah. >> Just git push I think actually will work as well. >> Cool.

[1:26:33] (external link, opens in new tab) >> okay. So, do you, do you want to add another test for another feature or do you want to finish for today? >> I think we should finish your finish for today. It's already 3 3:00 a.m. for me and I got work tomorrow. >> It's only 3:00 a.m., dude. It's very early. Still have time. I'm just kidding. >> actually, I would remove all those gray things over there at the top, >> like this one. >> I would Oh, yeah. >> I would just continue cleaning. I mean actually my my next things to do might be doing the

[1:27:06] (external link, opens in new tab) >> what do we do? >> Say say again >> what I what I said is that my next new things would be to to basically look at that fully surrounded and partially surrounded and see how we can make that nicer. >> Okay. >> But we'll do that maybe next time. Yeah. Are you happy? >> I think we still have a bit of refactoring to do. >> Sorry. >> Still. >> cool. >> Are you happy with how the code is turning out now or do you >> Yeah, I I find it interesting like before I was a little skeptical about it, but after refactoring it's like a lot cleaner, a lot more confident about it.

[1:27:44] (external link, opens in new tab) So, >> cool. >> Yeah. >> Okay. So, I'll see you maybe tomorrow. We'll see what happens. See you everyone. Thanks for hanging out with us. And cheers. >> Cheers. >> Bam. Okay, cool. That was nice. I now I'm feeling a bit productive.