در حال بارگذاری ...

One Indent per Method0:00

The next guideline that we'll cover is one that very, very much improved the quality of my code once I really forced myself to follow it. And that one is, one level of indentation per method. So I bet I know what you're thinking, wait a minute, as soon as we do a single loop and then we have to do a sub-loop, already we are at three levels of indentation, so this just isn't practical, right? Well, maybe that's the case, but maybe it's not. Let's review an example to see for ourselves. Imagine that we have some kind of BankAccountsCollection class. And when we instantiate it, we'll give ourselves an array of Account classes.

Building a FilterBy Method0:33

Imagine that we have some kind of BankAccountsCollection class. And when we instantiate it, we'll give ourselves an array of Account classes. So let's set up the constructor there. And now, we want to give ourselves a way to filter down all of our accounts according to some specific type. So if I have my bank accounts collection, but I want to filter that down only to savings accounts, how could we do that? Well, we have some kind of filterBy method, and we'll give it the account type. And now, within this method is where most of this lesson's discussion will take place. We'll start with the not very good route, and then later we'll refactor to improve it.

And now, within this method is where most of this lesson's discussion will take place. We'll start with the not very good route, and then later we'll refactor to improve it quite a bit. All right, so to start, if we're going to filter it, maybe you begin with a filtered array, and then you say for each account as account, then we want to make sure that the account's type is equal to what we specified here, like savings or checking. So maybe we have some kind of type method on the account, and if that's equal to what the user specifies, then we're almost ready to update the filtered array, but maybe we also want to make sure that we're dealing with an active account. So you do another check.

also want to make sure that we're dealing with an active account. So you do another check. If the account is active, then only on that condition do we update our array filtered, and then push a new item, account. And that looks good. So finally, we return our filtered result, and we're good to go. All right, having said that, I want you to pay attention to the indentation level. So to start, this doesn't count. This would be considered zero. It's the beginning of the method body.

Testing with Account Class2:18

This would be considered zero. It's the beginning of the method body. But then we have one indentation, and then a second, and then a third. So here, a very, very simple method, but already three levels of indentation. We can do better. But before we do that, I just want to continue this and make sure that it does in fact work. So we're going to place this all within the same file to keep it simple, and now we'll set up our Account class. So we know that we need to have a type associated with the account. That'll just be a string here.

So we know that we need to have a type associated with the account. That'll just be a string here. So build up our constructor, and then we need to offer a couple methods. type to fetch the type of the account, and isActive to determine if it's an active account. So let's do the first one, type. Return this.type. And then finally, isActive, and I'm just going to hard code this one in. We'll assume for the demo that every account is active. And mostly that's it. But one little side note here.

And mostly that's it. But one little side note here. Do we instantiate an account, or do we open a bank account? Well, the terminology that I've always used is open an account. So I want my code to reflect that when I can. So let's do this. public static function open, we accept the type, and all that this method will do is serve as a named constructor of sorts. So return new static, and pass in the type. Finally, we'll make this private, which means in order to open an account, you must call

So return new static, and pass in the type. Finally, we'll make this private, which means in order to open an account, you must call this method. So I think with that, we're ready to try this out. We'll start by building up an array of bank accounts, and we can do that now by saying account::open, and we'll do a checking, and then how about a total of four? So two savings accounts, and two checking accounts. Now let's set up our BankAccounts class, and pass in that array. And we'll save that to accounts. Finally, we call our filter method.

And we'll save that to accounts. Finally, we call our filter method. So if I only want my savings accounts, I'll say accounts.filterBy(savings). And lastly, var_dump the output to see what we get. If we did everything right, we should have an array of two account objects. Let's see. So from the terminal, we will run php on this file, and there you go, two account objects. If we instead want the checking accounts, then we run it, and now we have those. Great. So everything is working, but if we scroll up, I'm just not happy with this at all.

Refactoring Nested Conditions4:55

Great. So everything is working, but if we scroll up, I'm just not happy with this at all. The re-indentation levels break the rule, which more often than not, is a clear indication that I need to do some level of extraction. So let me show you the process that I typically use. Immediately, I will zone in on nested foreach statements or conditions. And that's just habit at this point. Next, I work from the inside out. So the deepest indentation, and slowly work my way out. So this is the third level of indentation.

So the deepest indentation, and slowly work my way out. So this is the third level of indentation. Can I clean this up? Well, immediately what I see is, we're really just checking to see if the account type is the one we requested, and also the account is active, then update this filtered array. So that means I can probably move this up to the condition above. Now I can remove this, and we've now removed one level of indentation. But next, I'm still not happy with this at all, and the reason why is because when I come back to this two months from now, I'm going to have to parse what this does in my head.

come back to this two months from now, I'm going to have to parse what this does in my head. I'm going to have to go over it and say, all right, if the account's type is okay with what we passed in, and also the account is active, then I can move on. That's way too much processing for me to do. So next you might think, well, just give it a nice comment here. Really what we're saying is, if the account is of the type that was requested, then move on. If the account is of the type that was requested, and then you're good to go, right? Well yeah, that definitely helps, but aren't you sort of missing something here?

If the account is of the type that was requested, and then you're good to go, right? Well yeah, that definitely helps, but aren't you sort of missing something here? If we need to add a comment to illustrate what some condition does, why don't we instead just extract a method name, like this. I'm going to extract a method using phpStorm, and now the key here is, what I might have written as a comment, I want to wrangle that into my method name as best as I can. So in this case, is of the type, that's really what I'm working with here. So maybe I can call it isOfType, and there you go. And I'm going to remove the doc block just to keep things short and sweet. So now, usually a very clear indication that you're on the right track is when you realize

And I'm going to remove the doc block just to keep things short and sweet. So now, usually a very clear indication that you're on the right track is when you realize that your comments have now become redundant. There's no need for this to exist, because we have a readable method that describes exactly what we are checking for. Next, if we scroll down, notice that not only is there no indentation whatsoever, but this method may now be reused elsewhere in the class if it's necessary. So we are on the right track here. But still, we're not done yet, because that refactor we just did wasn't as much for indentation. That was about readability, which is equally as important.

But still, we're not done yet, because that refactor we just did wasn't as much for indentation. That was about readability, which is equally as important. But still, if we add this up, we have two levels of indentation, and I'm just not happy with that right now. So what are some other things we might do? Well, if we take a step back and look over this, we're just filtering through our accounts and returning a subset of them, only the ones that have the type that we specify. So I think we've touched upon a key word here, filter. Maybe a foreach isn't actually the right choice. Maybe instead, we should use PHP's array_filter function.

Using array_filter Instead8:30

Maybe a foreach isn't actually the right choice. Maybe instead, we should use PHP's array_filter function. That's specifically what it was designed for, so let's make sure that we use it. array_filter. We will pass in our array of items, this accounts, and then for each one referenced as account, if we return something truthy, that will be included in the result set, and if it's instead falsy, then we will discard it. So that means I could move this section up here, like so. And then I will use account type so that we can access that value within the closure here. But next, notice that we no longer need to worry about building up a separate array.

And then I will use account type so that we can access that value within the closure here. But next, notice that we no longer need to worry about building up a separate array. That'll be done automatically by array_filter. So that means we could remove this entirely, and instead just return the results of this method call. And further, that means I can remove the foreach here completely. And next, we don't need that here. We could assign that to filtered, like so, however, we're just returning it at the bottom, which means I could remove the variable name completely, and delete this. Now check it out, we've achieved the exact same end result, but we have exactly one level

Moving Logic into Account9:37

which means I could remove the variable name completely, and delete this. Now check it out, we've achieved the exact same end result, but we have exactly one level of indentation, when originally we had three. And further, imagine if within those three levels of indentation, we had some else statements, where in some situations we were branching our logic. All of that stuff, especially six months from now, begins to add up, and your code becomes as a result, that much more difficult to take in. So to finish up, I want to make one final tweak here. Right now we're calling an isOfType method on the collection of bank accounts. But if we think about it, shouldn't it be the Account class's job to let us know if

Right now we're calling an isOfType method on the collection of bank accounts. But if we think about it, shouldn't it be the Account class's job to let us know if it's of a certain type? Right now, we're using a lot of query methods. Give me your type. Tell me if you're isActive. Rather than just asking the account, are you of a certain type? So instead, what if we extracted this from our BankAccounts class, and instead put it within Account? Like so.

within account? Like so. And we'll make that part of the public interface now. So at this point, we no longer need this account parameter. We can just say, is the type of this account equal to what is passed in? And also, is this account currently active? Now I want you to notice two benefits here. At this point, these no longer need to be part of our public interface, because really, they're just nicely named getters. And there are some downsides to using getters.

they're just nicely named getters. And there are some downsides to using getters. So by following this style of tell don't ask, we actually achieve better information hiding as a result. So that means these two can be private, and I'll push this guy up. Pretty cool, right? That means if we scroll up, now all we have to do is say, tell me if the account is of the type that I pass in. So let's see if this all works. Back at the terminal, we run it, and we get the exact same output.

So let's see if this all works. Back at the terminal, we run it, and we get the exact same output. But now, by following this approach, where we are super ultra sensitive to this idea of deep indentation levels, we actually improved the design and the readability of our class in the process. So remember, it's not just about achieving some arbitrary rule. It's about finding little techniques that help you improve your software.

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