Check out a free preview of the full Functional-Light JavaScript, v3 course:
The "Composition Illustration" Lesson is part of the full, Functional-Light JavaScript, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Kyle introduces composition by defining abstraction as the creation of semantic boundaries. An analogy to a candy factory is used to illustrate the process of drawing these boundaries and applying composition in code. - http://static.frontendmasters.com/resources/2019-05-06-functional-light-v3/functional-light-v3.pdf

Get Unlimited Access Now

Transcript from the "Composition Illustration" Lesson

[00:00:00]
>> Kyle: All right let's talk about composition. We briefly mentioned this one earlier as well when we're talking about point free let's dig into composition. Let's understand the idea of one function's output becoming the input to another function. Here's an example, I've got three numerary functions, a minus2, a triple and an increment.

[00:00:21] And they do exactly what you would expect, minus2 subtracts two, triple triples it, increment increments by one. On line six, I'm going to call increment with four, because that's my base shipping rate that I'm going to start with. Or that's one of my base inputs for calculating a shipping rate.

[00:00:40] And then that gives me a temporary variable. And then I'm going to pass that value line seven into the triple function. So I went from four to five and then I passed five into triple. Which triples it, that becomes 15. And I save that into temp. And finally, I pass that 15 value into the minus2 function line eight.

[00:01:02] And that gives me the end result which would have been my shipping rate being added to the total cost of this product. Okay, this is a scenario that we're going to use over the next several slides to try to illustrate the idea of composition. And what you need to get out of this, the take away that you should be looking for is becoming familiar enough with this pattern that you spot when one function call is producing an output that is then later routed to another function call.

[00:01:34] It is often the case that it'll end up in some kind of variable and then that variable gets passed. Sometimes you'll see it literally written with a nested like one call inside of another. But more often you'll see them assigned to variables, sometimes things like temporary variables like you see here.

[00:01:49] And you want to get to the point where you can recognize [SOUND] that's a composition. Okay? That's the take away. That's the final summary. Okay? So what I'm going to do to illustrate composition for you, is I'm going to ask you to switch your brain between the code scenario that we're looking at here.

[00:02:09] And I'm gonna ask you to look at a metaphor that I'm going to use to describe it, okay? As we talk about this metaphor, the first step that I want to address is this idea of abstraction. How many of you have heard that term before, abstraction? Okay? Abstraction is one of those terms that is thrown around in programming.

[00:02:28] And nobody really can pinpoint and say definitely, this is what I mean by abstraction. It seems to have lots of different meanings in lots of different places. But I want to talk about the original idea behind abstraction. The original idea behind abstraction is that you have two or more things in say a piece of code that are intertwined together.

[00:02:53] We could look at line six, seven and eight, and we could say that there are two distinct concepts happening here. And they're interwoven. One of the concept is that we're calculating a shipping rate and one of the concepts is we're adding that shipping rate to the base total for this order.

[00:03:11] Those are two distinct concerns, but in this particular piece of code they're wrapped up together. Okay? The initial original idea of abstraction was to tease apart two things which were otherwise intertwined together. To tease those two things apart so that they are separate. And by way of separation we insert in between them a semantic boundary.

[00:03:38] That allows us not to hide one or the other. That's what a lot of people think abstraction is about hiding. It's not about hiding, it's about separating. Abstraction is saying take these two things, separate them so that I can look at this thing and understand it or look at this thing and understand it.

[00:03:57] Without, while looking at this thing, having to worry about this one, or vice versa. By separating them, we make them easier to understand, easier to analyze. So how would we abstract lines six, seven, and eight. Not hide things, but rather separate things. That's what I want you to keep in the back of your minds as we go throughout this discussion.

[00:04:23] Okay? So, the metaphor I'm going to use and we're going to be mentally jumping back and forth. So, hopefully you've had your caffeine, hopefully you're ready to mentally jump back and forth between these two scenarios. For this scenario, I'm gonna ask you to play as if you are an engineer at a candy factory.

[00:04:38] Okay? And at the candy factory you have these machine setups like you see here. You got these machines with conveyor belts in between them, where they produce the candy step by step by step down the assembly line. Okay? So on the far right here, we see a machine that, you see my great art skills, I'm a pretty good artist here.

[00:04:56] You see this machine that takes melted chocolate, you pour in the melted chocolate, and what comes out on the bottom is these cooled blocks of chocolate, okay? That's what machine one does. Those cooled blocks of chocolate rumble down the conveyor belt to the left, they go to the next machine whose job is to chop it up into tiny little pieces.

[00:05:15] And so those tiny little pieces are coming out of that machine. They rumble down another conveyor belt and they fall into the third machine, whose job is to wrap them up in the nice candy wrappers. And those roll along to the next machine which packages and so on, okay.

[00:05:29] So in this candy factory, we got a couple of these contraptions, if you will. These machines set up on the factory floor and everything's going well. You're the engineer who's responsible for managing all these machines. One day the CEO, the owner of this, president or whatever of this candy factory comes to you and says, hey, you've been doing a really great job, but we've got a little bit of a problem.

[00:05:53] And I wanna see if you can think about how we could fix this problem? Okay? Because he says, you know, the problem that we have is that our competitors are producing a lot more chocolate more quickly than we are. Like they're producing three or four times as much chocolate every day as we are.

[00:06:11] And we're losing to them and we got to figure out a way to catch up. We need some way to catch up. So, the boss is basically saying, can you figure out some way for us to make more chocolates. Now you know that these machines can't be sped up, we can't make them run faster.

[00:06:29] So the only way to make more chocolates is to have more machines. We're going to have more of these setup. And the problem is we don't have room on the factory floor. They are taking up so much space. We only got a couple, we've only got room for a couple of these in the factory.

[00:06:43] So you begin to roll round at the back of your head thinking how could I make more room on the factory floor for more of these machines so that I can make more candy. We could keep up with our competitor. That's what you're going to be thinking as an engineer at this candy factory.

[00:06:59] Now I want to press pause on that scenario. And I want us to go back to that code snippet that we were just looking at. Remember the code snippet where I had those temp variables, okay. Those temp variables are kind of cluttering things up and they're not really benefiting us anywhere very much.

[00:07:16] And so we think you know what let's just get rid of the temp variables and let's just have each function call nested inside of another function call. Call increment four and then pass that to triple and pass that to minus2 and then, bam, we've calculated the shipping rate.

[00:07:31] Anybody every done this before? Have you ever nested function calls like that before? Okay. So whether you knew it or not, you were doing composition. That's a function composition. Taking the output of one function, making it the input of another function. We got rid of those nasty, ugly temp variables that were taking up too much space in our program.

[00:07:53] You with me? And we've cleaned up the code.
>> Kyle: Let's go back to the candy factory. You're the engineer and you've been thinking to yourself, you know, I think what we ought to do. I think the big problem is that those conveyor belts are taking up too much space.

[00:08:10] So you get this brilliant idea one day. You say, what if I just took out all the conveyor belts, and what if I just stack the machines right on top of each other? And I've got one machine at the very top where we'll be pouring the chocolate, the chocolate falls out of that machine directly into the next one.

[00:08:26] It falls out of that machine directly into the next one and so on and bam, problem solved. Because now I can install many, many more of these on the factory floor because I got rid of all that unnecessary clutter of all those conveyor belts, all those temporary variables.

[00:08:42] You with me? So you install this solution in the candy factory. And all of the sudden the factory starts producing more candy and everybody seems happy and the boss slaps you on the back and says great job. Things go well for six months. And then one day the boss comes to you and says, hey we've got another problem.

[00:09:05] I need to see if you can try to solve for us. We like the fact that we're able to produce more candy. But one of the problems with this new solution that you came up with, our factory, the line workers, they've been complaining because these machines being stacked on top of each other.

[00:09:20] It's very cluttered. There's wires all over the place and they have to remember to push the button at exactly the right time and there's too many buttons to push and too many wires. Is there some way that you could just make a single machine that they pour in the chocolate and out comes the wrapped candy?

[00:09:37] That's what the boss says. Right? You know because bosses they don't think in terms of reality and they just say, you engineer, go make it happen. Okay? So they're basically asking you to invent some kind of machine that does it all in one. Takes the cool chocolate, I mean, the melted chocolate at the top and spits out wrapped candies.

[00:09:54] Make it easier for all the factory workers. And you're thinking to yourself, well, even if I could do that, it would be difficult for me to maintain it. Each of those individual steps and pieces. I'm going to have to have some way to access what's going on, right?

[00:10:08] So this is what's rolling around in the back of your head. You're the engineer, you're trying to figure this stuff out. We have the same problem back in our code base. Which is that we've got the place where we're calculating our shipping and then we've got the place where we're adding that to the total.

[00:10:23] And these two things are all wired up. It's hard to reason about each one independently. So you think to yourself, I know I'm good engineer I know what I need to do. What I need to do is write a function. Make a function called shippingRate. Which does that work.

[00:10:41] It does minus2, triple, and increment. It takes in the value. And now look at line 12. Line 12 is much cleaner, because line 12 has semantically separated the two concerns. Line six is where we calculate how to do. Where we say how to do the shipping rate calculation.

[00:11:01] And line 12 is where we say what to do with it. Which is to add it into the order total. This is called an abstraction. And the semantic boundary that we inserted is the function name. The function named shippingRate is the semantic boundary between how to compute the shipping rate and what to do with the shipping rate.

[00:11:30]
>> Kyle: Those are the two separate concerns that previously were all intertwined together. But because we made a function, now they're nicely semantically separated.