تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Focus on Small Refactors0:35

Alright, so you get the basic idea. You've seen this many times. If I switch over to Sublime, this is all stored within a view called Scan. Now, a lot of HTML here, don't let this overwhelm you, I don't even want you to really worry about it. Just come along for the ride, and what you'll see, if I scroll down to our script, rather than focusing on large refactoring, instead, together, we're going to focus on the little things, little refactors. And I promise, if you do enough of them, they actually add up to substantial refactors. Alright, so let's get started.

to update a filter that is then passed to Algolia. And basically, in this case, it would just say, okay, Algolia only returned me the lessons where the ID is equal to this. Or the same for my favorites. Okay. So, if we switch back, yeah, just come along for the ride, don't take anything in other than what I'm showing you here. Now, the first thing I see right here are these filter sections. Well, these are what the checkboxes are bound to. So, for example, if I open up Chrome DevTools, we'll go into our scan view.

items that you happen to have. All right. So, now that we know, if we scroll up, let's take a look here. All right. Here is the MyLarikast section. That corresponds to this. So, you'll see that we have inputs here with a v-model equal to the thing that you would want to filter by. So, in progress, or completions, or watch laters, or favorites. Okay.

Group Filters Into Object2:40

So, in progress, or completions, or watchLaters, or favorites. Okay. Let's scroll back down. The first thing I'm thinking is, why don't we put those within an object instead? So, I'm going to say filters here, and then we'll have one completions, and all of these should default to false. So, watchLaters is false, favorites is false, and progress is false, and history is false. Okay. So, now I can get rid of those entirely. And I like the way that looks.

So, now I can get rid of those entirely. And I like the way that looks. Next, I need to update my vModel references. So again, just come along for the ride here. All right. vModel, filter by, filters.inProgress, this one would be completions, this next one is watchLaters, and this next one is favorites, and one more for history. Okay. So, let's scroll back down. Let's see what else.

Refactor Preference Toggling3:36

So, let's scroll back down. Let's see what else. We'll talk about this in a minute. I want to see if there's any references to filter by. Yes. All right. So, we have some sections here. So, let's talk about what's going on. When the User clicks on one of these checkboxes, we immediately call this method toggleUserPreference.

When the user clicks on one of these checkboxes, we immediately call this method toggleUserPreference. So, I noted that one thing that happens when you click on a checkbox is we uncheck any of the other items within this list. So, the way we're doing it, at least for this demo here, is we have a list of all of those filters. So, immediately, I'm thinking, well, we already defined it once as a data attribute, but now we're doing it again. All right. Maybe we can refactor that.

Now it has everything but watchLaters. Okay. So, we can see, once we have that array, all right, well, for each item within that array, we're just reading this together. Refinements. So, we don't know what's happening here, but we have a comment. You see words. So, it sounds like that will become watchLaters. All right. Then we look for this filterByWatchLater.

All right. Then we look for this filterByWatchLaters. So, we're basically saying right here, this filterByWatchLaters equals false. Right? So, we're just taking that vModel data attribute, and we're setting it to false for all of the items that you did not click. But now, in this case, it's no longer filterBy. It is this.filters, and then we can get rid of that entirely. However, you can see some changes already, right, because up here, these don't need to be capitalized.

However, you can see some changes already, right, because up here, these don't need to be capitalized. We were doing that earlier when we had each of these stored as filterByWatchLaters. Right? That's what we were doing earlier, but we don't have to do that anymore, which means if this refinement is equal to watchLaters, that's fine because that's a property already stored. So, I'm going to get rid of that entirely, which is nice. Now that we've simplified the code, I think I can even put this all on its own line, or Prettier is going to force me to do this, but that's okay.

So, I'm going to rename this to otherRefinements, at least to start. The otherRefinements, except the one the user clicked. Anyways, let's come back, see if we broke anything. So, I will select an item. We're not getting the updates to the right. However, if I select new items, at the very least, we are toggling as we would expect. Okay. So, that's one little refactor. Next, for this otherRefinements variable, we're not referencing it anywhere else. Which means, I bet we can get rid of the variable entirely, and do something like this, and

Next, for this other refinements variable, we're not referencing it anywhere else. Which means, I bet we can get rid of the variable entirely, and do something like this, and then reformat. All right. Get this array of items, filter it down to only the ones that were not clicked, and then for each one, turn it off. All right. What next? Well, I noted earlier, it looks like we're repeating this list of items. So if we scroll up one more time, yeah, we have those here.

Well, I noted earlier, it looks like we're repeating this list of items. So if we scroll up one more time, yeah, we have those here. So I don't see any reason to reproduce that. This this.filters. But yeah, we can't do that, because that's going to give us an object of each of the items, right? So, we'd have watchLaters, and completions. What we really want to do is filter through all of the keys. So I can say Object.keys, this.filters. Now we'll have watchLaters, and completions, and the other three items.

Generate Query From Filters8:04

But sometimes this is good for your own coding. If you embrace the repetition, it then becomes that much more clear when a refactor is necessary. So here you can see, well, if this item exists, then build up a query for that item. Now, before, think of it sort of like an SQL query that we're then going to pass down Golia. So we have the same thing here. If you clicked on WatchLaters, then build up a filter, an SQL query. It's not really SQL, but it's close enough. And then if favorites, you'll notice it's kind of the same thing over and over. So immediately I'm thinking, all right, well, I bet we can clean this up drastically, like this, object.keys, this.filters.

So immediately I'm thinking, all right, well, I bet we can clean this up drastically, like this, object.keys, this.filters. So now, once again, we have an array of all of the User refinements, all of these items here. Okay. Let's say for each one, we'll call it refinement. Well, let's just take one of these blocks and move it up. If this.filters.refinement, so basically, yeah, we're saying if this.filters.inProgress? If that checkbox was checked, then we're going to set a filter.

The next thing I can see here is, all right, let's continue on. Once again, small refactors. We're not even looking at the full code yet. We're just looking at bits and pieces and thinking, are there ways to clean up this small portion of code? All right. Next, I can see this query parameters.filters. Okay. So let's see where this is being used. All right.

So let's see where this is being used. All right. That's the only place. So with that in mind, do I really need to declare this? Because we're not using it within the template. So instead I'm going to get rid of that and let's go back to where we referenced it. There it is. That means we never use this and instead we're going to update the store. Now you don't really need to know this, but behind the scenes, when I update these query parameters, the Algolia components automatically going to detect that and refresh the results.

you know what I'm thinking? We're still assuming that there could be multiple filter, multiple user refinements here, but we're not doing that anymore. You can only click one or the other. So you can see we're filtering through all of those refinements and we're checking to see if the user clicked that, but we already know when we get to this point in the code, there will only be one checkbox clicked, which means is there any reason to filter through all of them? I don't think so. So I'm going to comment that out and instead say the filter will be this.query for the

I don't think so. So I'm going to comment that out and instead say the filter will be this.query for the toggled attribute. And remember the toggled attribute will be the name of the filter. So for this one, it would be inProgress. For this one, it's completions. For this one, it's watchLaters. So here we're just building up the SQL, the SQL-like query for that filter. All right, let's come back, refresh, click an item, and you can see we're getting the exact same thing as we had before.

If I'm only using this filter in one place, I think we can just as easily inline it there. And this is what we get. Deselect all of the other items and then update the query parameters with the new filter. And again, behind the scenes, Algolia will pick up on that change and refresh the results. So to my eyes, this method is looking fairly good. If you want, you know, you might extract this to a method like deselectUserRefinements except for the toggledAttribute, you know, if you want to be very clear here. That will accept the attribute and let's update that. There we go. Yeah, I don't really mind it either way, but that might be a little more clear.

Improve Naming Consistency13:38

Anyways, let's move on. We can come back to that. So now I'm just going to go method by method. So here you can see we're building up the query, the SQL like query for, but we've named it preference. And once again, this is an important thing. It's a common mistake where you will have this concept, this variable name, where you call it one thing over here, but then way over here you refer to it as something else. Maybe a common example is like here you refer to the user's ID as ID, but over here you refer to it as user.

Maybe a common example is like here you refer to the User’s ID as ID, but over here you refer to it as user. And then over, over here, you refer to it as user ID. And they all refer to the exact same thing, but you're using three different names. So in this case, and again, that would be a reason why I would want to get rid of attribute there. But here we could either call this the filter or the refinement. We've been using this term refinement, so I'm going to stick with that. Okay. So we're building that up.

Okay. So we're building that up. That method looks fairly clean. We're just building up a query there. This method is now 10 times cleaner than it was before. As part of that refactor, we extracted this method here. Next, we have some helpers here, like calculating when the publish date was. Nothing wrong there. The video type, this is something we're using over here. Actually, let's undo everything, and then if I scroll back, yeah, so we have the ability

I made a little comment to myself that this is basically the JavaScript version of ucwords. You may know in php, you can say ucwords(foo), and you'll get foo, right? But in JavaScript, there isn't anything like that. So people often refer to a regular expression like this. But in our case, you know what? I think we can get away with just make the first letter capital, and then every other letter can be as it was before. We don't need anything too fancy. So let's say the $type is currently lesson.

We don't need anything too fancy. So let's say the type is currently lesson. We want to turn that into lesson. Or if the type is series, we want to turn that into series. Okay. Well, we could say the type, give me the character at 0. So give me the first character there, and we're going to capitalize that. And then I want to add basically the rest of the characters. So let's say type substring, begin at the first character, but it's 0 index, so it's really the second character.

So let's say type substring, begin at the first character, but it's zero index, so it's really the second character. So we're basically going to say, get the substring starting at the first index. So now that should give us series. Once again, a small refactor, but I think it's worth it. So let's update that, and I should be able to get rid of this. Come back, and if I scroll down, we still get the same thing. One other thing we might do, this is fine. We could also do maybe a ternary. So we could say return.

We could also do maybe a ternary. So we could say return. Well, actually, let me show you real quick. We could just return the type. And if I come back and refresh, you'll see we get episode, lesson, and series. Honestly, for my eyes, that's fine. But I do want to make it clear what the difference between a lesson and an episode is. So what we could say is, return, well, does the type equal lesson? If that's the case, return standalone lesson. Otherwise, just return what it was before.

If that's the case, return standalone lesson. Otherwise, just return what it was before. Come back, refresh, and now we have what we had before, but again, we're focusing on small refactors. Okay, the next thing, we have this method completed. So this is our way of checking, was the lesson completed? And behind the scenes, that is what will update the styling here, to have a strikethrough in the arrow. So if I come back, I honestly, I think this is perfectly fine. But we could also take all of this out, and now let's just look for where we called it,

So if I come back, I honestly, I think this is perfectly fine. But we could also take all of this out, and now let's just look for where we called it, completed. Yeah, it looks like there's only two references to it. So I think this is honestly okay as well. Completions includes the ID. I don't think we've reduced readability at all, so I think that's a decent refactor. Okay, so let's keep scrolling down. Ignore this, obviously, this is going to be something we tackle, but I'm just doing methods for now.

Ignore this, obviously, this is going to be something we tackle, but I'm just doing methods for now. I'm focusing on small things for the 10th time, and actually, on that note, often when I'm refactoring code, it's not like I'm thinking, what is this great design that I need to work towards? Often, I'm focusing on little things, like how can I reduce indentation? How can I make this variable name more clear? How can I get rid of that if statement? I'm focusing on very small things, but once again, as I've noted earlier, those small things, when you stack them up, actually add up to a full design.

We don't need any loop whatsoever. And then once again here, even though we're looping and filtering, it's very clean using the API there. Okay, videoType is now clean. On page change, scroll to the top, no problem there. And then we have our thumbnailPath. All of these things are perfectly fine to my eyes. So if we scroll up, this is the next thing that catches my attention, and this is an important thing. Often, when you're looking for things to refactor, just scroll the file, scroll the class or

Refactor Default Refinements19:03

important thing. Often, when you're looking for things to refactor, just scroll the file, scroll the class or the script, and just wait to see if something jumps out at you, where you think, ooh, not sure about that. That feels kind of clunky. I immediately see that here. So what's going on? Well, when the component is mounted, this section here handles, you don't really need to know this, but it handles the default refinements that Algolia will select. So for example, if I were to say, let's select this option by default, I could say, refinement.

to know this, but it handles the default refinements that Algolia will select. So for example, if I were to say, let's select this option by default, I could say, refinement is the skill facet, and the name that we are refining is PHP. Okay, now you'll see that that option is selected when the page loads. So that's all we're doing here. Look in the query string. If we have refinement and name, then we're going to toggle that. And that's just the Algolia API. But next, I noted that we have this section built on top of that. So here we're checking, well, do we have watch laters in the query string?

But next, I noted that we have this section built on top of that. So here we're checking, well, do we have watchLaters in the query string? If so, find that checkbox and check it. So let's give that one a shot. Let's do favorites. Okay, now that option is selected. And again, that's being done here. But I'm noticing all of this repetition once again. So why don't we instead do another loop? Select keys, and for each one, we're going to check.

So why don't we instead do another loop? Select dot keys, and for each one, we're going to check. So I'm going to grab this bit of code that's being repeated, and we'll place it in there. Okay, now, rather than hard coding this, we're just going to look for the refinement. So basically, did the user type in about watch laters? If we found that, then grab the checkbox and click it. And in this case, I'm using querySelector. You could just as easily use view refs. So you'll notice here, let's see, each input has an ID, userWatchLatersRefinement. Why don't we normalize that?

and click it, or try to track down that checkbox and click it. So refresh, and now you can see we have clicked favorites. Let's do, how about history? And now that one has been clicked. So that was a good refactor. So what does all of this do now? We've learned both of these sections handle the default refinements. So what if we created a method called activateDefaultRefinements? All right. Paste that in and refactor.

All right. Paste that in and refactor. Okay, so now let's go through this one more time. So we have some standard stuff, some default coloring we've hardcoded. We have our search store, our filters. When the element is created, this is some trickery. Don't even worry about it. Nothing interesting. But when the component has mounted, all right, we'll activate the default refinement. So activate the correct checkboxes here.

that's for another video where we dig into Algolia components a bit more because I think we could refactor some of this to custom components. But for this lesson, we are mostly focused on the little things. And as we've learned, so often these little tweaks, these little refactors can add up, and they can drastically affect the readability of your code.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟