Identifying God Objects0:00
Okay, so let's move on to the next option you might consider when trying to clean up a big monstrous God object. So once again, you'll almost always want to look at your User class, usually the first victim, and then also the class or the model that represents the core of your application, the core thing that your application does. So for example, for a blog, it'll be a Post model. For a Laracast, it might be a video.php model. That can grow and grow if I'm not careful. If it's some kind of e-commerce site, it might be an Item class or a Product class or maybe an Order class that you need to worry about.
If it's some kind of e-commerce site, it might be an Item class or a Product class or maybe an Order class that you need to worry about. Anyways, if we take a look at this, you'll see I've added just a handful of dummy methods here. So once again, we're thinking about this idea that maybe you can complete a Video or a Lesson or a Post or whatever is relevant for your project. And we can see we want to keep this nice API. So you've decided you want the User to be able to do something like this, User complete Video, right? Or to fetch all of the Videos they've completed, User completions.
video, right? Or to fetch all of the videos they've completed, userCompletions. Or to uncomplete, I don't know, would that be uncomplete or incomplete? I don't know. I'm calling it uncomplete. Maybe that would be the inverse. So you like the way that API works, but yeah, once again, we've added four, we've got four methods here, completions, complete, uncomplete, and then completed would check to see if the user completed the given video. So userCompletedVideo would return a Boolean.
User API Examples1:29
user completed the given video. So user completed video would return a Boolean. Or you might want to even name that hasCompleted to make it a little more clear that you're getting a Boolean. But yeah, either way, for that single task or operation, we have four different methods. So once again, you can imagine over the course of a year or two, how this grows and grows into this God object we keep talking about. Next, we have another section here. And this looks like it's related to a forum. So a user can start a conversation, startConversation, and then you know, you would
And this looks like it's related to a forum. So a User can start a conversation, startConversation, and then you know, you would new up a Conversation and pass it to that method. And then a User can also reply to a Conversation with a Reply. Once again, you've decided that this is the API you want to provide. Okay, well, we're trying to clean things up. Once again, imagine that there's many, many more methods here, and you're trying to decode and detangle all of this crap. Alright, so here's the second option you might consider. Simply create a trait.
Using Traits to Extract2:29
Alright, so here's the second option you might consider. Simply create a trait. And sometimes people don't like this because as they see it, it kind of goes against the idea of what a trait is. So a trait is almost a way to simulate multi inheritance. But generally people think of it as like a mixin. So if you create a trait, you can then mix that in to any class that requires that functionality. And that's great. But you know what, I'm also fine with you using a trait, even if it never gets used anywhere else.
Creating Completable Trait2:56
But you know what, I'm also fine with you using a trait, even if it never gets used anywhere else. We're just going to use it to clean the space a bit. And we'll talk about that a bit more because some people don't like that either. But anyways, let's review an example. So I can see that these methods are related to a User completing or working with completions. So I'm going to take all of that, and we're going to create a trait instead. So why don't we say, well, a User can complete videos. So maybe we'll call the trait Completable. Now it's very possible we'll have a namespace there of like App\Videos\Completable.
So maybe we'll call the trait Completable. Now it's very possible we'll have a namespace there of like App\Videos\Completable. But I'm just going to keep it in the app directory for now. So Completable. As always, let's set our namespace App. And then once again, trait Completable. And I will paste those in. Okay, that's all there is to it. We've now created a trait, and we've included it in this class. Now what was I talking about where I said some people don't like this?
way. Or used in the wrong way. You know what? I think it's fine. But as always, make up your own mind. Next we can do the same thing here. So once again, we have two methods. But maybe in real life, there's five or six methods. And you want to keep that API. Remember, extracting a class is an option.
And you want to keep that API. Remember, extracting a class is an option. We already talked about that. But also, extracting even a trait is very much a valid option as well. It's up to you to decide which one to do. OK. So I'm going to cut that out. And what are we going to do now? Well, these methods correspond to a User participating in the forum. Now actually, a quick tip on naming.
Naming Traits Properly5:26
Well, these methods correspond to a User participating in the forum. Now actually, a quick tip on naming. A lot of people do things like this. ForumTrait. Just every possible class or trait gets a suffix here. Generally, I'm not a big fan of that. ForumTrait, not a fan. Instead, if the methods represent that a User can participate in the forum, why don't I say participatesInForum? I think that's great.
say participates in forum? I think that's great. So let's do that now. Participates in forum. And then once again, we have our namespace and our trait. And I will paste those in. OK. So let's go back to our User class. Now we've reviewed a second option you might consider when cleaning up a big, bad User god object, which is extracting not a whole new object and a whole new design, but simply
Evaluating Trait Tradeoffs6:07
Now we've reviewed a second option you might consider when cleaning up a big, bad User god object, which is extracting not a whole new object and a whole new design, but simply a trait, which like I said earlier, is sort of like cleaning up your room by taking each of the items and putting them in their own drawer. Now if we take a look at the User class, it's nice and simple again. But if you need to dig down to, for example, how a User can complete videos, you can see that functionality. And further, if you want to see how the User participates in the forum, you can review that functionality. And a nice benefit to this is, yes, the User class isn't nearly as dramatic and overwhelming.
It's not like one is infinitely better 100% of the time. You have to consider, is it better to kind of clean things up over here and extract this responsibility elsewhere, or is it very important that I retain this API that I really want? And if that's the case, yeah, extracting even a single use Trait is a good, interesting way to go.
