Encapsulating Model Behavior 0:00Here, I'm back in my project tasks controller. And in the store method, where we add a new task to the project, you can see that we chose this method called addTask. Now it's true, we could have used, if we visit the project model, I could have just done this directly. So we could have done something like this. Project tasks create, and then pass in our request data. And I find that newcomers often are confused by this. They think to themselves, well, what's the point of adding a method here if I can just call this code directly?They think to themselves, well, what's the point of adding a method here if I can just call this code directly? And the answer is, well, two things. One, it's much more readable to say project addTask versus project get this relationship, then call this eloquent method, and then pass in these attributes that refer to database fields. We can tuck that away. Or, in other words, the project model can encapsulate what it means to add a task. All we need to know on the outside is, hey, here are the attributes. I want to add a task.All we need to know on the outside is, hey, here are the attributes. I want to add a task. But then the project model can be responsible, fully responsible, for what it means to actually do that. Our controller doesn't care if we're using eloquent or anything else. It just wants to know, okay, I had this project model. Add a task to it. But now if we scroll down to the update method, we're kind of doing the opposite here. We're calling eloquent's update method. And once again, we're passing through what essentially translates to a database field.We're calling eloquent's update method. And once again, we're passing through what essentially translates to a database field. Now, here's a key thing to understand. I am not one to beat you up over this. And in fact, if you look in my own projects, I have no doubt you will find things very much like this. And this is why it's very important to understand when things are a benefit, and then often when it just doesn't matter either way. Maybe this is the only place, what we can see right here, we are completing a task. Maybe this is the only place I will ever perform this logic.Maybe this is the only place, what we can see right here, we are completing a task. Maybe this is the only place I will ever perform this logic. And if that's the case, whether or not we call task update here, or we call a method on project, it just doesn't matter. But other times it does matter. So this is your responsibility. For your own projects, you have to decide, is it important that I do this? Is it important that I encapsulate this logic for completing a task? Or does it just not matter? And I think based upon what you're doing, you'll fall on both sides of the spectrum Defining Task Completion 2:07Or does it just not matter? And I think based upon what you're doing, you'll fall on both sides of the spectrum there, which is a good thing. So in this case, what are we doing again? We are marking the task as completed. So we are completing the task. Now if we think about it, if I'm building an application dedicated to projects and tasks, that's a really important thing, don't you think? That's a key function that our application does. So I do want to represent that in my domain.That's a key function that our application does. So I do want to represent that in my domain. So with that in mind, if I have a task, I want to expose the behavior that it can be completed. So I will call complete. That's what I want to do here. And I think you'll agree, that looks much more readable. And if down the line, I need to dig in to see what exactly it means to complete a task, I can do that. But at this level, on the controller level, I don't really care.I can do that. But at this level, on the controller level, I don't really care. I just want to say, okay, I have my task. Mark yourself as complete. Do whatever you need to do to mark it as complete. Or in other words, we're telling task what we want it to do. We're not telling it how to do it, which is what we're kind of doing here. We're saying, okay, task, I'm just going to take over. I want you to be marked as completed. I know what to do.I want you to be marked as completed. I know what to do. I'm a micromanager. Just let me do it. I'll go and find the necessary database field, and I will take care of it. You just sit there. I will do the work. All right? That's kind of the difference between these two. With this approach, you do the work. Adding a Complete Method 3:24That's kind of the difference between these two. With this approach, you do the work. You encapsulate your logic. With this approach, I don't trust you. I will do the work for you. That's an important distinction, and it's a key component of object-oriented programming. All right, so let's give this a shot. On my task model, I now want to declare or expose that it can be completed. To do that, we can call update, and I will mark completed to true. So if we switch back to our controller now, now a quick note.To do that, we can call update, and I will mark completed to true. So if we switch back to our controller now, now a quick note. Here we are marking the task as completed, but that's actually not the same as what we had here. This was updating the completed status based upon a value in the request. It's not just marking it as complete. So it sounds like we still want to pass through request as completed, but maybe we should accept a parameter or an argument to check this. Okay, so here we could say completed. Well by default, if you call complete, we're going to set it to true.Okay, so here we could say completed. Well by default, if you call complete, we're going to set it to true. But by some chance, if you want to say task complete false, well then that should do the opposite. And we're going to make that a little more readable in just a second, so stick around. Okay, so I will set this like so, or once again, I can use compact. Okay, so why don't we just take a moment and see if this works. I will switch back. Let's check. How about this one?Let's check. How about this one? And now it works. Let's do the opposite. Great, that works as well. So we've now improved encapsulation for our task model. If we go back to our controller, notice at this point the controller has no awareness of the underlying database attributes or fields. It doesn't care at all. It just wants to know, hey, I need to add a task, or hey, I need to complete a task. Handling Incomplete State 5:02It doesn't care at all. It just wants to know, hey, I need to add a task, or hey, I need to complete a task. But like I said, in certain situations, like if we mark this as incomplete, well, it's a little confusing because we're calling complete, but then we're passing a Boolean that determines how we proceed. So we're basically doing this in certain cases, right? And in general, I don't like doing this, especially down the line when you're dealing with domains that aren't as obvious and simple as projects and tasks. Things like this can be a little frustrating because you see false and you think, well, I don't know even what the opposite is, so what is it doing on false versus true?Things like this can be a little frustrating because you see false and you think, well, I don't know even what the opposite is, so what is it doing on false versus true? So often in these situations, if you want to keep this, what you do is add a second method. So if you can complete a task, then it stands to reason that you should be able to do the opposite, mark it as incomplete. Now again, you could do this. You could say this update completed is false, and that would be fine. However, we're already calling update here. We're basically doing the same thing.However, we're already calling update here. We're basically doing the same thing. We're just toggling a Boolean. And because this already accepts a Boolean, well, if you want, you could just say this complete false. We're doing the same thing, so we're taking that confusing Boolean. We're just abstracting it away behind a readable method that more clearly describes what we're doing here. So now, again, I think this is okay. But if you want, you could do something like if request has completed, well, then we willSo now, again, I think this is okay. But if you want, you could do something like if request has completed, well, then we will mark it as complete. Otherwise, we will mark it as incomplete. So that would be the long form way. Or I'll show you two other ways. I often see this written. You could say request has completed, then task complete. So we're just going to convert this to the ternary form. You could do that.So we're just going to convert this to the ternary form. You could do that. Or a third form would be to set the method. So we could say request has completed, then the method name will be complete, otherwise incomplete. And then you call the method dynamically. So that's what? Four different options. So this is what we had originally, then this one, then this approach, then this approach, and then this approach. Benefits of Rich Models 7:07So this is what we had originally, then this one, then this approach, then this approach, and then this approach. Let's just stick with what we have here, but again, any of these are fine. All right, so now we've gotten a number of benefits here. Our controller is more readable, and now our Eloquent models are exposing a good bit more behavior. Sometimes you may find that your Eloquent model is empty. You're just using it as a quick database adapter. And in many situations, honestly, that's fine. It all depends upon what you're building.And in many situations, honestly, that's fine. It all depends upon what you're building. However, I think as you insert more and more behavior into these models and abilities, I think your project will improve as a result. For any given model, I can now see, well, what can I do with it? What abilities or affordances does it offer? Well, in this case, a task can be completed, it can be incompleted, it can be associated with a project, and if we switch over to project, we can see, okay, a project can add a task. So very quickly, we can begin visualizing what exactly we can and can't do with these various classes and objects.So very quickly, we can begin visualizing what exactly we can and can't do with these various classes and objects.