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

Readability vs Code Length0:07

We often measure readability by number of lines of code, but less code doesn't necessarily mean more readable. Take an example of a method with a return statement using a array. Now this works and it's just one line of code, but I'd argue it's pretty dense and that makes it hard to read. Just reformatting with a few line breaks can break out the individual paths and make this more readable.

with a few line breaks can break out the individual paths and make this more readable. Refactoring to a guard clause makes it even more readable and reveals other potential refactor. Now, I've gone from one line of code to five lines of code, but I'd argue this is much more readable. This demonstrates length alone is not really a good measurement of code readability all the same. Code length still motivates us to refactor. In fact, I'd say it's often the biggest motivator.

Three-Step Refactor Process0:56

Code length still motivates us to refactor. In fact, I'd say it's often the biggest motivator. I want us to use that motivation, but I want us to add two steps before we refactor: a review step and a regroup step. Let's demonstrate the process of breaking up the following big block of code. Going through each step. The first thing we wanna do is review its level. This is kind of like its context.

Assess Code Reading Level1:20

The first thing we wanna do is review its level. This is kind of like its context and it's determined by the location and the role of the code. Is it within a class or a function? Is it deep within the application or at the surface? Is it within a model or a controller? Armed with the context and our goal to make the code more human readable, we create a sort of reading level.

and our goal to make the code more human readable, we create a sort of reading level. You can think of this much like an academic reading level. For example, we expect a fourth grader to read at a fourth grade level. We wouldn't want a fourth grader to read at a second grade level, and we don't expect a fourth grader to read at an eighth grade level. The same goes for code.

to read at an eighth grade level. The same goes for code. Ideally, the code fits the current level, a sort of Goldilocks zone. If it's too low level, we're reading more code than we need to, and if it's too high level, we'll have to dig deeper into the application. Going back to our code snippet, we can see that this is a controller within a Laravel application and the Laravel framework follows an MVC paradigm.

that this is a controller within a Laravel application and the Laravel framework follows an MVC paradigm. Traditionally, that means it's responsible for mediating between the model and the view. With Laravel being a web framework, controllers are most often responsible for handling a request and returning a response. So for now, we simply wanna label its level and we can say it's a controller. More specifically, it should handle

and we can say it's a controller. More specifically, it should handle the request response. We may also look at the role of the code to determine a bit more about the context. In this case, the authenticated method is responsible for returning a response for the authenticated user. So let's add that Knowing the level will allow us to make informed decisions during the refactor step.

Regroup Into Sub-Blocks3:07

Knowing the level will allow us to make informed decisions during the refactor step. The next step in evaluating a big block of code is to regroup it into sub blocks. You basically scroll through the code add line breaks, and a little comment for what each block does. This outlines the code, making it easier to understand and spot duplication. It also allows us to revisit the original intent of the code.

It also allows us to revisit the original intent of the code. Often the existing code can act like a box, so it's hard for us to think beyond the current implementation. By regrouping in the code, we re abstract it and allow us to think outside of that box. Furthermore, the implementation of the code can be a little subjective. That is one programmer might implement the code different than another, but if we focus on what the code does

That is one programmer might implement the code different than another, but if we focus on what the code does or its action, we can remove some of the subjectivity. It's pretty rare that two programmers would disagree on what the code does. Let's get back to this authenticated method and regroup it. I'm just gonna go line by line, add line breaks and a comment to each sub block. So this very first sub block seems to figure out if this is an Ajax request or not.

So this very first sub block seems to figure out if this is an Ajax request or not. So determines if this is an Ajax request. Let's move down to the next block of code. It's this if statement and it seems to determine what role the User has and return a response based on that. In this case, redirecting them to the admin dashboard. So I'll come back up here, I'll add a comment, redirect user

In this case, redirecting them to the admin dashboard. So I'll come back up here, I'll add a comment, redirect user to admin dashboard. Moving on, we're down to this next block of code. Similarly, it redirects user to teacher dashboard. And as we keep going, we're starting to pick up on a bit of a pattern here. Both of these bottom blocks do the same thing. So I'm just going to copy my previous comment, add 'em here,

Both of these bottom blocks do the same thing. So I'm just going to copy my previous comment, add 'em here, and we'll change this back to parentDashboard and studentDashboard. Now we're at the end of our big block and I'm gonna use PHPStorm to collapse these sections so we can focus strictly on the comments that we've left. So reviewing our sub blocks, we determine if it's an Ajax request, and then we basically redirect the user.

Refactor Using Two Questions5:40

we determine if it's an Ajax request, and then we basically redirect the User. Said another way we redirect the User to their dashboard and the response is based on if it's Ajax or not. Now we're ready for the refactor step and sometimes that can feel a little daunting, but now that we've reviewed the code for its level and regrouped it into sub blocks, the process of refactoring is much easier. Now we really just need to go through each sub block

of refactoring is much easier. Now we really just need to go through each sub block and ask two questions. Can this code be performed in a native way, meaning with code that already exists, either from the framework or the language or elsewhere in the code base? And if not, we ask the second question, does the code fit the current level? Let's get back and finish refactoring our authenticated method.

Let's get back and finish refactoring our authenticated method. Jumping into the first sub lock, we wanna determine if this is an Ajax request. Right now we're checking this ourselves. Is there a way to do this natively? There actually is the request object actually has an ajax method. This method determines if the request is an Ajax. So can this code be written in a native way?

This method determines if the request is an Ajax. So can this code be written in a native way? The answer is actually yes. Laravel offers us an Ajax method on the request object. If we jump down into this method, we actually see that it performs a similar check against the headers. So there's a native way to do this. Armed with this, we can look at how the ajax variable is used. In fact, it's only ever used in the conditionals.

how the Ajax variable is used. In fact, it's only ever used in the conditionals. So I would actually inline this variable and I can do that with phpstorm. Once I get rid of our temporary comment, we've actually removed that entire sub block. Alright, let's collapse the code again and look at the remaining sub blocks. As we noticed before, all of these pretty much do the same thing.

As we noticed before, all of these pretty much do the same thing. They effectively redirect to the User dashboard. That action lines up with the current level of the code. But if we re-expand the inner blocks, we can see a lot of code duplication. So we can ask ourself, can this code be done in a native way? Well, given that this is a custom response to a specific URL, I would say no.

Well, given that this is a custom response to a specific URL, I would say no. That brings us to the second question. Does this code belong at the current reading level? And I would say yes, because this sends the response, but this block is nonetheless duplicated. To refactor that duplication, we could abstract it in this case to a private method. So I'll cut this logic. We'll go down to the bottom of the class.

So I'll cut this logic. We'll go down to the bottom of the class and say private function, redirectToDashboard and we'll need to pass it whether or not it should be ajax and the url. We'll finish out the method signature and paste. Now we no longer pass in the request object. We just pass in an ajax object and the url is now dynamic. Now that we have this private method, we can go back.

in the URL is now dynamic. Now that we have this private method, we can go back and remove the duplication by calling it. Instead, we'll return this redirect to dashboard request Ajax and pass it the correct dashboard URL. Let's do the same for the other sub blocks. So we'll paste this here, here, and here, and then I'll collapse that last part.

So we'll paste this here, here, and here, and then I'll collapse that last part. Let's jump out and give that a quick format. So we've streamlined by abstracting the duplication into a private method, but we still have each of these duplicated sub blocks. So we'll ask the questions again, can this be done in a native way? The answer is no because it's very specific to the User role in our application.

The answer is no because it's very specific to the User role in our application. So to our second question, does this belong at this level? Now the redirection does, but does the controller really need to know that role two is for the teacher dashboard, not necessarily. It only cares that a specific User has a specific dashboard. Knowing which role maps to which dashboard is a rather low-level detail, one that's specific to the context of the User.

is a rather low level detail, one that's specific to the context of the User. What I'd like to see is a method that existed on User that performed this mapping. If that existed, we would be able to do something like userDashboard(). Having such a method would remove the need to do the mapping at this level and therefore all of the duplication for each of the different dashboards.

therefore all of the duplication for each of the different dashboards. So now I can remove the additional sub blocks and remove the check specific to the User role. And with that, we've collapsed our authenticated method to a single line and it reads perfectly with the level of the code for the authenticated user redirect to their user dashboard. Now in this case, we reduced a big block of code to a single line.

Refactoring Shell Game11:43

Now in this case, we reduced a big block of code to a single line. That's not always going to be the case. And actually, if we think about it, we didn't really reduce it to a single line of code. The only way we were able to actually remove code is when it existed natively. When it didn't, we really moved the code around based on its reading level. So it's really a bit of a shell game,

around based on its reading level. So it's really a bit of a shell game, and it's important to remember that that's one of the reasons refactoring can feel hard. Often we think we have to completely remove the code, but code is a bit of a mathematical equation. What we do to one side needs to happen to the other side. That means if we remove five lines of code from one part of the application, will need to move it to another. Keeping this in mind

of the application, will need to move it to another. Keeping this in mind and following this three step process will help you refactor big blocks of code with ease.

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