Javascript Design Patterns

I’d like to start speaking about design patterns by quoting Christopher Alexander, founder of modern patterns who influenced many industries around the globe, including our own.

…each pattern represents our current best guess as to what arrangement of the physical virtual environment will work to solve the problem presented.

As you can see, I slightly modified original version of what mister Christopher said and boom, we have a clear explanation of what patterns are. In our case, a pattern would be an arrangement of code which when applied to a specific problem, solves the problem in the most elegant and efficient way.

Another worth quoting definition of patterns comes from a very popular JS patterns book written by Addy Osmani:

A pattern is a reusable solution that can be applied to commonly occurring problems in software design - in our case - in writing JavaScript web applications. Another way of looking at patterns are as templates for how we solve problems - ones which can be used in quite a few different situations.

If we carefully observe both definitions, we can come to a conclusion that patterns are simply “templates” applicable to specific problems.

With all this being said, how come that design patterns are so misunderstood among developers ?

Be warned, here comes my personal opinion about this matter so don’t take it too much for granted ‘cause you know how they say, opinions are like assholes, everybody has one.

In my opinion, lack of understanding of patterns comes due to two simple things:

  • Framework-oriented programming aka step 1,…n-developers (will explain what I mean by this term)
  • Bad approach to software architecture e.g. not defining what the problem is and which tools are the right ones for the given problem.

Framework-oriented programming aka step 1,…n-developers

While some people will maybe get filled with hatred while reading this part, this sadly is a fact. With the high interest in tech due rich job eco-system, we see more and more people coming into industry. Tech bootcamps are booming (I’m a mentor at one), tutorials and videos are pretty much everywhere and it has never been easier to pick a specific framework, learn steps in a very generic way, e.g. require this, download this, connect this and you have a full stack application running.

Due to this, people never actually get to a point of learning patterns because they are already given full-featured framework(s) which offer everything you need to build an enterprise ready platform.

That being said, I came with a term 1,…n-developer which relates to people who are successfully using given frameworks but have absolutely no clue how those frameworks operate and which core API’s are they running on.

Bad approach to software architecture

I work for an AI startup focusing on deep learning, creative skills and critical problem solving. Creativity and problem solving skills are the hardest to acquire and sooner then later, will be the main decider when it comes to recruiting and us being relevant on the market. But why am I even talking about this ?

Problem solving skills believe it or not are also patterns, slightly different ones and they focus on one, most probably hardest thing ever, asking the right questions. To bring you close to what I just said, I will quote mister Einstein:

If I had an hour to solve a problem, I would spend 55 minutes looking for the right questions to ask.

I slightly shortened the original version but when aggregated, it means just that.

If we translate all this theory into practice and design patterns, we realize that in order to efficiently use “right tools for the given problem”, we need to define and understand the problem and then focus on solving it.

Design patterns are just like a toolbox in your garage. You have bunch of tools in there but you will not use a hammer to glue your’s wife porcelain cup. Design patterns for solving the “wife problem” aren’t invented yet. :0)

To get yourself to a point of asking the right questions, you need to deeply understand the problem and what you’re trying to solve. You need to identify existing and possible future flows of the system, research and familiarize yourself with similar problems some other individuals ran into and use an existing pattern or if you are lucky, invent your own.

But beware, not every solution is a pattern. Patterns are proven and community accepted solutions for common problems. Not every piece of code is a pattern even though there’s a high chance that your code, regardless of how you wrote it will at least a little bit, fall under some specific category.

For more specific explanation of this, refer to the free JS Patterns book by Addy Osmani.

Types of Patterns

In this article, we will divide patterns into three categories:

  • Creational - constructor, composition, module, factory, singleton
  • Structural - decorator, facade, flyweight
  • Behavioral - command, mediator, observer

Keep in mind that this is not a comprehensive list of patterns but rather, list of most commonly used ones in Javascript.

Creational Design Patterns

During your Javascript sail and the learning path, I’m sure that you’ve stumbled upon something like “Everything in Javascript is an Object”. Not to get into this specific subject now, indeed in Javascript we use and operate on objects a lot.

Just like the name implies, Creation-al design patterns relate to creating Javascript Objects in various ways. Ability to work with the same data type in various ways allowed us to implement those patterns at times when our structure finds it the most optimal.

Constructor Pattern

If you are a developer coming from other languages like C++, C#, Java, Constructor pattern in Javascript would be something most closest to a Class in the languages mentioned before. Since Javascript didn’t have classes (up until ES6 aka ES2015 aka Javascript 6), we were creating instances using the Constructor Pattern;

An example of creating instances of our “class” looks like this:

function Fruit(name) {
  this.name = name; // we are assigning this.name to whatever we pass to our constructor function, e.g. on line 6 and 7 we are passing apple and orange
  this.printFruit = function() { // each newly created instance will have its own printFruit method. We'll learn later how using Prototype we can share one common method between instances instead of creating a new one for each object
    console.log('The fruit is ' + this.name);
  }
// implicitly returns "this"
}

var apple = new Fruit('apple');
var orange = new Fruit('orange');
// apple and orange variables are called instances of the Fruit constructor aka "Class"


apple.printFruit(); // The fruit is apple
orange.printFruit(); // The fruit is orange

As you may notice, a Constructor is just a regular function with its name capitalized. This naming convention is community driven and is how we differentiate normal functions from Constructor functions in Javascript. You can choose not to capitalize the first letter of your Constructor functions but beware, you’ll get rains of hatred falling on you.

There are several things to understand in this example and all are very important when it comes to writing Object-Oriented Javascript. To fully wrap your head around this Pattern, its essential to be familiar with the “this” and “new” keywords.

If you take a look at line 6, you will notice a comment: implicitly returns “this”. What this means is that every time we invoke our Constructor with a “new” keyword, Constructor will return “this” and assign it to the instance (variable on the left). Values and methods held on “this” will be those we initially assigned in the Constructor function, in our case, name and printFruit method. To simplify it even more in a human language, whatever we attach on “this” will be part of that specific instance e.g. var apple, var orange. So basically, when using “new” keyword in front of a function, a new object is being created with specified blueprint aka schema in our constructor. Reason I used terms “blueprint and schema” is because Constructor is just a function that creates new objects that have identical properties (blueprint aka schema) but optional values (in our case apple and orange variables both have name and printFruit but the name itself is optional depending on what we passed to the constructor when we created those objects).

Also, you’ve noticed a term “instance or instantiation” showing up several time. If we leave this article for a second and ask Google what instantiation is, we’ll get the following answer:

In programming, instantiation is the creation of a real instance or particular realization of an abstraction or template such as a class of objects or a computer process.

In Javascript, you will be reading and hearing about word “instance” a lot and what it really is, is an Object created (instantiated) using a a Constructor function e.g. new ConstructorFunction.

So to summarize what new keyword does:

  • Creates a new object with specified blueprint aka schema
  • Binds “this” to the newly created instance - (binding in a more human language means relating, associating, pointing, depends on the context)
  • Implicitly returns “this” - if English is not your main language, implicitly in this context means that the operation return this was done for us automatically in the language implementation, we don’t need to manually (explicitly) do it
  • Links (connects aka adds reference aka pointer) to the Object’s Prototype - This is the last one for a reason and at this point, you are not suppose to understand it. We are going to talk about Prototypes just now so be patient for next few paragraphs and you’ll get it

Prototypes

If we pay attention to the code above, we notice that for each newly created instance, a printFruit method is created. While this is not a big issue today due to amounts of RAM, computation power and all of the sexy hardware, we should still remove this redundancy and make only one method for that all our instances will reuse.

Let’s make some slight modifications and add our printFruit method to the Constructors prototype:

function Fruit(name) {
  this.name = name;
}

Fruit.prototype.printFruit = function() {
  console.log('The fruit is ' + this.name);
}

var apple = new Fruit('apple');
var orange = new Fruit('orange');

apple.printFruit();
orange.printFruit();

As you can see, our code doesn’t differ too much from the initial one but a new keyword “Prototype” is introduced. Prototype is simply an object to which all instances of a specific Constructor point to (in this case, our two instances apple and orange both point to Fruit.prototype). Prototype can hold both, methods and properties so if we wanted to have a shared-property across our instances, we could simply add it like this:

Fruit.prototype.something = "some value";

apple.something // some value
orange.something // some value

We can add as many methods and properties as we want to the Constructor’s prototype and they will all be “globally” accessible to their instances. Note that adding properties to a constructor is not recommended. If you want to define a default value for a property of an instance, define it in the constructor function.

Reason for this is simple:

function Fruit(name) {
    this.name = name; 
}

Fruit.prototype.fruits= ['apple', 'kiwi'];

Fruit.prototype.printFruits = function () { 
    console.log(this.name, this.fruits); 
};

var banana = new Fruit('Banana');
var grapefruit = new Fruit('Grapefruit');


banana.printFruits(); // ['apple', 'kiwi']
grapefruit.printFruits(); // ['apple', 'kiwi']

banana.fruits.push('watermelon');

banana.printFruits(); // ['apple', 'kiwi', 'watermelon']
grapefruit.printFruits(); // ['apple', 'kiwi', 'watermelon']

As you can see, the fruits array we created is now shared among members, therefor, each time we mutate the state (e.g. .push(‘watermelon’)), change will reflect to all members.

Prototype Chain (commonly known as inheritance in Object-Oriented Programming)

Prototype Chain is ability of one Constructor to inherit methods and props from another one. To illustrate this, imagine we are building a Vehicle factory project and we want to abstract methods and props that all vehicles share in common.

  function Vehicle(color, wheels) {
    this.color = color;
    this.wheels = wheels;
  }

We’ve created a Vehicle constructor and we assumed that all other vehicle types e.g. Car, Truck etc. are sharing those 3 props. But before we actually “inherit” those props, let’s first instinctively approach this problem assuming we don’t know that inheritance even exists.

Naturally, we would create identical constructor just with different name.

  function Car(color, wheels) {
    this.color = color;
    this.wheels = wheels;
  }

As you can see, I created a new constructor named Car but what I did is I copy/pasted those same props Vehicle constructor has and I broke one of the golden rules in programming, DRY (Don’t repeat yourself). If I needed a Truck type for instance too, I would pretty much do the same and we would duplicate same props every time.

So, this is where inheritence comes to a rescue. Instead of duplicating our props, we do a little trick using .call method.

  function Car(color, wheels) {
    Vehicle.call(this, color, wheels);
  }

Call method will invoke Vehicle constructor on every new instance we create off of Car e.g.

var car = new Car("red", 4)

To be continued…