Defining Fluent Interfaces0:00
Yet another option you have when you're trying to refactor some code, make it a little more elegant, make it a little more user-friendly, all of that stuff. One more option is to use a fluent interface. And I think these sort of get a bad rap. And from what I've seen, it kind of leads people to think you should never use them. You'll come across articles like this, Marco's a great developer, there are some good points in this, but still, it has the effect of making you think, I should just stay away from that completely. And that's definitely not the case. So, well, first step, what exactly is a fluent interface? Okay, it's just a pattern where you chain method calls together to create a more readable, more natural, more descriptive instruction. Now, generally, this takes the shape of an API or a class where each of the relevant methods return the same instance.
Laravel Testing Example0:39
readable, more natural, more descriptive instruction. Now, generally, this takes the shape of an API or a class where each of the relevant methods return the same instance. It doesn't have to be that. I'll show you an example at the end where we don't do that. But in general, that's usually what folks are referring to. So, I'm going to show you an example using Laravel's testing helpers. And this is actually one of the things that I personally put a lot of effort into building. Anyways, normally, you're familiar with PHPUnit assertions, right? So, you make some kind of call, you get the results, let's get rid of this entirely, and then you perform an assertion, right? assertEquals or assertContains, provide the needle, compare that against the haystack, you get the basic idea, right? This is pretty common, and it works in plenty of situations. But you also may find that it's not quite as enjoyable
to check, oh, the needle comes first, and then the haystack. But with this approach, it's irrelevant. You don't have to provide the haystack, because we do that for you behind the scenes. So, I would say this is a perfect example and a perfect use case for a fluent interface. Now, behind the scenes, it's going to be very simple. Here's the shape something like this would take. You have your method, visit. You perform an action, and because we want it to be fluent, we return the same object. Okay? That's specifically what allows us to continue chaining. Otherwise, if I did not have this here, yeah, I would have to say something like response, and then I would continue on and say this, see, and then I'm basically back in the exact same thing again, where I have to pass all of this stuff through. Not what we want. So, instead, for any related method, we return the object, and that allows me to continue chaining. Then,
Trade-offs and Downsides3:37
implements this very pattern in a number of places. So, this is what I mean when people say it's evil. Yeah, there's trade-offs. There are some things to consider. A good note is, when you do it in this way, it's a little bit harder to test. Now, in this case, this is test-specific code, so it doesn't matter as much. But for your own APIs, that could be a concern. If you intend to decorate this sort of code, it does make it a little bit more difficult. And that's why, yeah, you just have to consider the ups and downs of each approach. And what you'll find is, in some cases, it's kind of the perfect instruction, and it makes your code that much more natural to work with. Let me show you a few more examples. How about this one? Not even php. We're doing this in JavaScript. So, as you know, with Laravel Elixir, in your gulpfile.js, you can chain things as much as you want. So, if I want to, using the latest version of Elixir, compile this down with Webpack, I could do that.
Elixir Fluent API Example4:19
you know, with Laravel Elixir, in your gulpfile.js, you can chain things as much as you want. So, if I want to, using the latest version of Elixir, compile this down with Webpack, I could do that. If I need to version a file, I could do that. If I want to use BrowserSync, yeah, you get the idea, right? Once again, you would call this a fluent API. That's exactly what it is. Especially for small projects, where you want to say, yeah, compile down this Sass, and then I want to version some kind of folder. Then you're done. It's really simple. And notice how much this benefits the user of your code. That's really important. Don't just write code for yourself, write code and APIs that others want to use. So, even though this is JavaScript, I'll show you how we implement that. If I go into Bootstrap, enable extension. Okay. So, don't worry about this too much. But for each task that Elixir provides, like mix.less or mix.sass, those are
Pipeline and Dispatcher Chaining5:04
how we implement that. If I go into Bootstrap, enable extension. Okay. So, don't worry about this too much. But for each task that Elixir provides, like mix.less or mix.sass, those are stored within this mixins object. So, when you call mix.sass or mix.less, it's going to trigger this function. And notice it returns the object, the full recipe list of mixins that we offer. So, once again, we're following the same pattern there. What else? How about this? Let's go to Laravel's Pipeline class. This actually may be a class you don't even know about. You can leverage it if you want. But generally, this is something that Laravel uses behind the scenes. Okay. Let's look for something like send. All right. So, we have a method. And all it is, you don't even need to know what it does specifically. You just need to know this is a glorified setter, and then it returns the object. So, other people may say foo equals new foo. And then foo set thing equal to
to know what it does specifically. You just need to know this is a glorified setter, and then it returns the object. So, other people may say foo equals new Foo. And then foo set thing equal to thing. And then they continue on, you know. Well, yeah, you could do that if you want. Or you could just say foo. You could use a glorified static constructor. And then you could use your nice setter here. Set thing, like so. And then continue chaining. Once again, that's a fluent interface. So, notice send and then through, and it returns the object. Via, and then it returns the object. Then, which accepts a closure, it performs some work, and then it calls your closure. And that's the final step. So, it doesn't return anything at that point. Okay. So, if we take a look at maybe Laravel's bus dispatcher. Let's look for dispatch. Yeah. Here is the usage for that fluent interface. This, pipeline, and here's where we begin. send this command through the pipes,
Low-level Fluent Pattern6:39
look at maybe Laravel's bus dispatcher. Let's look for dispatch. Yeah. Here is the usage for that fluent interface. This, pipeline, and here's where we begin. Send this command through the pipes, and then resolve the command out of the container and call a handle method. Easy and simple, right? Can't argue with that. Now, let me show you one last example. It doesn't always have to be like some big API with 10 different methods that return the object. You can even do this at a low level, just to make your code that much more simple and natural to write. So, here's a lesson where we talked about authentication without passwords. Check it out if you want. But here's what I want to show you. If we go into the AuthenticatesUser class we wrote, this is a form of a fluent interface. Very, very simple. Almost to the point that you may not even realize that we're following any pattern there. And that's good. You don't always have to fill your head with patterns.
interface. Very, very simple. Almost to the point that you may not even realize that we're following any pattern there. And that's good. You don't always have to fill your head with patterns. These are little techniques you can learn. File them away, and then they're in your tool belt for life. You don't always have to label them before you write them. You know, it's like a guitar player who's been playing for 20 years. They may have learned all of these fancy modes and different ways to play scales, but when they're taking a solo, they're not thinking, well, I'm implementing the Phrygian mode here, and I can play. No, they're not thinking that. They're just playing, because it's part of their tool set at that point. Okay, anyways, if we take a look at this invite method, we have our entry point, and then we adopt this fluent interface pattern to create the instruction. So notice one benefit of this is, if I want to know how I invite a User,
invite method, we have our entry point, and then we adopt this fluent interface pattern to create the instruction. So notice one benefit of this is, if I want to know how I invite a User, when I take a look at this method, it makes perfect sense. I don't have to parse anything. I don't even need comments here to describe what's happening, because the fluent interface does it for me. validate the request, create a token, and send it to them. Now, here's the final thing I want to show you. If we take a look at validate request, it returns the object. Great. create token does not return this object. So this was the important thing I wanted to talk about. In order to create a fluent API, typically it will return the current object, but it doesn't have to. As long as whatever object you do return honors this contract, so to speak, then you're fine. So in this case, that's exactly what I've done. create token is actually returning an instance.
As long as whatever object you do return honors this contract, so to speak, then you're fine. So in this case, that's exactly what I've done. createToken is actually returning an instance of this LoginToken class, and then we're calling a send method not on this object, but on the LoginToken object. And if we take a look at that, LoginToken, a little tip there. A lot of people don't know that. On GitHub, if you hit T, you can search through all of the files. That's a good one to know. Anyways, now if we scroll down, here's the send method that we trigger. And if you want, you can get really mad about that Mail facade in the process. But I don't care. Sorry, not sorry. Anyways, yeah, so that's yet another little technique you can put in your tool belt. And that's the important thing to remember. Do not feel like you have to memorize every single one of these, and you have to find a place for each of these techniques in all of
