Consider Composition
Tags: javascript, beginners, oop, functional
Published: 2020-11-08 15:38:06

> “Favor object composition over class inheritance” 

the Gang of Four, “Design Patterns: Elements of Reusable Object-Oriented Software”

![Banana](https://dev-to-uploads.s3.amazonaws.com/i/go0xjtftz3b793czo55b.jpg)

> “...the problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.” 

∼ Joe Armstrong, “Coders at Work”

# Overview

Rather than focusing on the OOP capabilities of JS, many folks come to appreciate the relative simplicity and ease of using _composition_ over _inheritance._ 

Put simply:

1. **_Inheritance_ focuses on establishing 'is a' relationships.** Although this practice somewhat dominates the industry, one of the drawbacks is that we must carefully try to plan and anticipate many use cases for 'things' ahead of time. It's not too difficult to overlook something and then have to struggle to backtrack.
2. **_Composition_ is more about 'has a' relationship - or we focus on what something should be able to do. Essentially, we 'mix in' or compose whatever functionality from wherever we might need it, 'on the fly.' This tends to make us a bit more adaptable, and even the syntax and implementation can be easier to follow.**

---

This [video](https://youtu.be/wfMtDGfHWpA) is a great 'primer' for the concepts expressed here.

Also, as a reference to the 'inheritance version' of the code I go through here: 

{% link https://dev.to/codefinity/is-js-an-oop-language-2dne %}

---

# Composition

In [a previous post,](https://dev.to/codefinity/object-assign-and-spread-kcl) we explored creating new _objects_ 'on the fly_ using _object composition._ Now we'll take it to the next level. 

## Function Factories 🏭 to Encapsulate 'Functionality'

Again, in order to build up a `Student` or `Faculty` member, we will want to _compose_ them from some other objects that represent different pieces of functionality.

```javascript
const Greeter = (name) => ({
  greet() {
    return `👋🏽. My name is, ${name}.`;
  },
});

const CourseAdder = () => ({
  addCourse(newCourse) {
    this.currentCourses = [newCourse, ...this.currentCourses];
  },
});

const RaiseEarner = () => ({
  giveRaise(raiseAmt) {
    this.salary += raiseAmt;
  },
});
```

Done! We have 3 'things' that we can compose together to build 'bigger' things. Again, we capitalize to denote that these are 'things' made to be reused or composed (same convention with React components).

Each of these is a _function factory_ that returns an _object._ that 'wraps' 🎁 a _method_ to implement some specific functionalities.

```javascript
const Greeter = (name) => ({
  greet() {
    return `👋🏽. My name is, ${name}.`;
```

`Greeter` encapsulates `name` in a _closure._ It means that after `Greeter` is _invoked,_ instead of `name` being _garbage collected,_ **`name` will stick around as long as it's needed by `greet`.**

We'll see 👇🏽 that `Greeter` will be _composed_ into `Student` and `Faculty`. Whenever we create a `Student`, for example, the `name` that we use will be 'enclosed' in `greet`. Each time `greet` is run 🏃🏽‍♂️ on a `Student`, that 'enclosed' `name` will be _referenced._

## `Student` and `Faculty`

```javascript
const Student = ({ id, name, age, major, credits, gpa, currentCourses }) => ({
  id,
  name,
  age,
  major,
  credits,
  gpa,
  currentCourses,
  ...Greeter(name),
  ...CourseAdder(),
});

const Faculty = ({ id, name, age, tenured, salary }) => ({
  id,
  name,
  age,
  tenured,
  salary,
  ...Greeter(name),
  ...RaiseEarner(),
});
```

Both `Faculty` and `Greeter` 'mix in' 👩🏽‍🍳 the desired functionalities. For example: `...Greeter(name),`. We can say that each of these _has a_ `Greeter`.

When we mix in `Greeter`, we are _binding_ the `name` - there's that _closure._ 

`RaiseEarner` and `CourseAdder` are _invoked_ and _bound_ with a `this`- `this.currentCourses` and `this.salary`.

Next, we'll instantiate `mark`, an instance of `Student` and `richard`, an instance of `Faculty`.

```javascript
const mark = Student({
  id: 1124289,
  name: "Mark Galloway",
  age: 53,
  major: "Undeclared",
  credits: {
    current: 12,
    cumulative: 20,
  },
  gpa: {
    current: 3.4,
    cumulative: 3.66,
  },
  currentCourses: ["Calc I", "Chemistry", "American History"],
});

const richard = Faculty({
  id: 224567,
  name: "Richard Fleir",
  age: 72,
  tenured: true,
  salary: 77552,
});
```

All we do is pass in their unique properties, our _function factories_ crank them out.

Testing things out:

```javascript
mark.addCourse("Psych");
richard.giveRaise(5000);

console.log(mark.greet(), richard.greet());
console.log(mark, richard);
```

We can see:

```bash
👋🏽. My name is, Mark Galloway. 👋🏽. My name is, Richard Fleir.
{
  id: 1124289,
  name: 'Mark Galloway',
  age: 53,
  major: 'Undeclared',
  credits: { current: 12, cumulative: 20 },
  gpa: { current: 3.4, cumulative: 3.66 },
  currentCourses: [ 'Psych', 'Calc I', 'Chemistry', 'American History' ],
  greet: [Function: greet],
  addCourse: [Function: addCourse]
} {
  id: 224567,
  name: 'Richard Fleir',
  age: 72,
  tenured: true,
  salary: 82552,
  greet: [Function: greet],
  giveRaise: [Function: giveRaise]
}
```

# The Main Advantage Over Inheritance

I prefer this implementation better, both syntactically and conceptually. I like to think of what things 'do' rather than what they 'are.'

But...here's a 'real' advantage. What if, we have a `Student`...that gets hired on to teach also? So...a `FacultyStudent` - one that can add courses and/or might get a raise. 

A possibly unpredicted situation such as this really shows where _composition_ shines ✨.

## More Inheritance? 👎🏽

Maybe. But...what is a `FacultyStudent`...should it extend from `Student` or `Faculty`? In classical OOP, this is where you might create an _interface_ - a means to encapsulate functionality that can be implemented by various _classes._ Fine.

## More Composition 👍🏽

How about this instead?

```javascript
const FacultyStudent = ({
  id,
  name,
  age,
  major,
  credits,
  gpa,
  currentCourses,
  tenured,
  salary,
}) => ({
  id,
  name,
  age,
  major,
  credits,
  gpa,
  currentCourses,
  tenured,
  salary,

  // Composition!
  ...Greeter(name),
  ...CourseAdder(),
  ...RaiseEarner(),
});

const lawrence = FacultyStudent({
  id: 1124399,
  name: "Lawrence Pearbaum",
  age: 55,
  major: "CIS",
  credits: {
    current: 12,
    cumulative: 0,
  },
  gpa: {
    current: 0.0,
    cumulative: 0.0,
  },
  currentCourses: ["JavaScript I"],
  tenured: false,
  salary: 48000,
});

lawrence.addCourse("JavaScript II");
lawrence.giveRaise(2000);

console.log(lawrence.greet(), lawrence);
```

```bash
👋🏽. My name is, Lawrence Pearbaum. {
  id: 1124399,
  name: 'Lawrence Pearbaum',
  age: 55,
  major: 'CIS',
  credits: { current: 12, cumulative: 0 },
  gpa: { current: 0, cumulative: 0 },
  currentCourses: [ 'JavaScript II', 'JavaScript I' ],
  tenured: false,
  salary: 50000,
  greet: [Function: greet],
  addCourse: [Function: addCourse],
  giveRaise: [Function: giveRaise]
}
```

Essentially, we can just keep applying the same concepts over and over and _compose_ 'on the fly'... "all night long!" 🎵 

---

All together now, and IK that was a lot! Thanks for sticking around.

{% replit @CodeFinity/Composition %}

---

**Updated 1:** If this topic is of interest to you, I refer you to this excellent article that's a few years old but still presents some of the same information in a slightly different way: 

{% medium https://medium.com/javascript-scene/javascript-factory-functions-vs-constructor-functions-vs-classes-2f22ceddf33e %}