Some Thoughts on the Awesomeness of Function and Object Composition in JavaScript After Reading JavaScript Allonge

| Comments

Update 25-05-2015: Reginald Braithwaite has released his “sixth” version of JavaScript Allongé. The book has been greatly updated to include new ES6 (ES2015) constructs that make this book even more awesome. Go read it! or buy it

The place is Luleå, a place in the farthest reaches of the north of Sweden. The time is late, and it is cold outside, cold as it gets, -25°C. The world this far north is covered in snow, even the rivers, and the seas are frozen. A hard environment to live in, yet the perfect environment and time to read cozy in bed! :)

Last night I finished reading JavaScript Allongé on my beloved Kindle and I wanted to share with you some of the awesome things I learned, specially regarding function composition, functional programming and how to write beautiful, idiomatic, expressive and intentional JavaScript by taking advantage of its functional character.

JavaScript Allongé

In C# the unit of composition are usually classes, we design our applications, our domain models, by creating small classes with a single responsibility and composing these classes together (directly or using design patterns) to achieve a goal or solve a problem. This does not mean that we cannot compose functions/methods in C# [1] but the language doesn’t lend itself to do it as well as other languages such as JavaScript.

In JavaScript, probably due to it’s dynamic character and sparse syntax, we can easily compose both functions and objects. We will start looking at how we can compose functions. My goal is to define a series of functions that have a single responsibility and combine them into new functions that provide a richer functionality and result in more readable, intentional, explicit, terse, reusable JavaScript code. Let’s see some examples of how we can achieve that:

Function Composition

I’ll Call You Maybe

How many times do we write guard clauses to our code? The classic if this argument is null then don’t execute this code? What if we instead of writing that if clause one time again we could extract this functionality in its very own function?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function maybe (fn) {
  return function (argument) {
    if (argument !== null && argument !== void 0) {
        return fn(argument);
    }
  }
}

// or in a generalized version for multiple arguments

function maybe (fn) {
  return function () {
    var i;

    if (arguments.length === 0) {
      return
    }
    else {
      for (i = 0; i < arguments.length; ++i) {
        if (arguments[i] == null) return
      }
      return fn.apply(this, arguments)
    }
  }
}

And use it like this:

1
2
3
4
5
6
7
8
9
10
function call(person){
    console.log('Calling ' + person);
}

var callMaybe = maybe(call);

callMaybe('jaime');
// => Calling Jaime
callMaybe()
// => undefined

Now we have a maybe function that we can decorate any other function we want with and a much more intentional JavaScript. When I read this code I immediately understand it.

Once

I have read code many times where the author had an intention when writing it in regards to how it should be used, a policy of sorts, but never got the time or the thought to make that policy explicit. Some time later another programmer visits this code, attempts to use it in a way it was not intended or modifies it in the “wrong” way and boom! Chaos and mayhem.

An example of this could be writing a function and ensuring that is only executed once. We can write our code and leave this policy as a comment, or completely undocummented or we can do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function once(fn){
  var called = false;
  return function(arg){
    if (!called){
      return fn.apply(this, arguments);
      called = true;
    }
  }
}

function initialize(){
    // some code
    console.log('initialize was called');
}

var initializeOnce = once(initialize);
initializeOnce();
// => initialized was called
initalizeOnce();
// => undefined

And now anybody that comes and reads this code will for sure understand that this function is supposed to be executed only once. And not only that, it is a policy enforced by the code itself.

Before and After

Do you need to do something before or after executing a piece of code? Logging? Transactions? any other cross-cutting concern? You can define these before and after decorators:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function before (decoration) {
  return function (fn) {
    return function () {
      decoration.apply(this, arguments);
      return fn.apply(this, arguments);
    }
  }
}

// and conversely

function after (decoration) {
  return function (fn) {
    return function () {
      var result = fn.apply(this, arguments);
      decoration.apply(this, arguments);
      return result;
    }
  }
}

And use it like:

1
2
3
4
5
6
7
8
9
10
var logDocuments = function(documents){
    console.log('logging some documents: ' + documents);
};
var logDocumentsFirst = before(logDocuments);

var saveDocuments = function(documents){
    // save documents;
};

var logAndSaveDocuments = logDocumentsFirst(saveDocuments);

You could also uncurry (make it take all arguments instead of one at a time) the before function and use it like this as well:

1
2
3
4
5
6
7
8
function before(fn, decoration){
  return function () {
    decoration.apply(this, arguments);
    return fn.apply(this, arguments);
  }
}

var logAndSaveDocuments = before(saveDocuments, function(docs){ console.log("log documents: " + documents);});

Not? None? Any? All?

What about composing predicates?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
function not(fn){
    return function(){
        return !fn.apply(this, arguments);
    }
}

function any(){
    var fns = arguments;
    return function(){
        var args = arguments;
        // using underscore here for simplicity
        return _.any(fns, function(fn){ fn.apply(null, args);})
    }
}

function isGreaterThan(x) {
  return function(y){
    return y > x;
  }
}

function IsEqualTo(x) {
  return function(y){
    return y === x;
  }
}

function IsSmallerThan(x){
   return function(y) {
     return y < x;
   }
}

var isGreaterOrEqualThan5 = any(isEqualTo(5), isGreaterThan(5));
var isNotGreaterAndEqualThan5 = not(isGreaterOrEqualThan5)

isGreaterOrEqualThan5(10)
=> true
isNotGreaterAndEqualThan5(10)
=> false

// and you can let your mind wander 
// about other possible uses for this ad infinitum

Method composition

I have separated method composition from function composition, because when it comes to methods in JavaScript, you really need to be careful about the context in which they are executed, which is the value of this. When composing methods you will need set the context to the current object by implementing context agnostic method decorators (use apply or call to explicitely set the value of this). For instance:

1
2
3
4
5
6
7
function maybe (fn) {
  return function (argument) {
    if (argument != null) {
      return fn.call(this, argument); // here we set the context of `fn` to `this`
    }
  }
}

instead of:

1
2
3
4
5
6
7
function maybe (fn) {
  return function (argument) {
    if (argument != null) {
        fn(argument);
    }
  }
}

And here we have an example of method composition when building fluent interfaces.

Fluent Interfaces

I love writing fluent interfaces as a programmatic API for services or classes that are meant to be used by my colleagues or other software developers. It usually involves using a fluent builder pattern like this one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public interface IApplicationConfigurationBuilder {
    ApplicationConfiguration Build();
    IReminderConfiguration AddReminder();
}

public interface IReminderConfiguration {
    IReminderConfiguration OfType<TReminder>() where TReminder : IReminder;
    IReminderConfiguration ThatIsScheduled(Periodically periodicity);
    IReminderConfiguration Starting(DateTime startingDate);
    IApplicationConfigurationBuilder Done();
}

public class ApplicationConfigurationBuilder : IApplicationConfigurationBuilder, IReminderConfiguration, ... {}

// This would enable us to write something like this:

var configuration = ApplicationConfigurationBuilder
    .New()
      .AddReminder()
          .OfType<DueDateReminder>()
          .ThatIsScheduled(Periodically.EachDay)
          .Starting(DateTime.Now)
      .Done()
    // more configurations regarding other aspects of the application
    .Build();

In JavaScript it could look like this (and I am reusing JavaScript Allongé’s example here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function Cake () {}

 extend(Cake.prototype, {
   setFlavour: function (flavour) {
     this.flavour = flavour;
     return this
   },
   setLayers: function (layers) {
     this.layers = layers;
     return this
   },
   bake: function () {
     // do some baking
     return this
   }
});

// that when used would look like

var cake = new Cake().
  setFlavour('chocolate').
  setLayers(3).
  bake();

We can however find a better way. We can extract the fluency from each method into a fluent method decorator that can then be applied to any method:

1
2
3
4
5
6
function fluent (methodBody) {
  return function () {
    methodBody.apply(this, arguments);
    return this;
  }
}

And then we can use to rewrite the previous fluent interface example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 extend(Cake.prototype, {
   setFlavour: fluent(function (flavour) {
     this.flavour = flavour;
   }),
   setLayers: fluent(function (layers) {
     this.layers = layers;
   }),
   bake: fluent(function () {
     // do some baking
   })
});

// that when used would look like
// the previous example

var cake = new Cake().
  setFlavour('chocolate').
  setLayers(3).
  bake();

Cool right? Less code and you make the fluency explicit and easily reusable. :)

A Recipe for Function/Method Composition

Can we generalize a recipe or procedure to follow to write more composable JavaScript? I would say:

  1. Read your code
  2. Identify Responsibilities
  3. Factor
  4. Compose
  5. Profit

That and you can take advantage of the numerous functions within underscore, lodash or allong.es.

Object Composition

In a similar way to what we’ve seen so far, JavaScript easily allows us to compose objects in order to create new objects with a richer functionality via mixins. I am going to steal and simplify JavaScript Allongé’s To-Do list example below where we add coloring behavior to a To-Do through a mixin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// the ToDo
function Todo (name) {
  this.name = name || 'Untitled';
  this.done = false;
};

Todo.prototype.do = function () {
  this.done = true;
};

Todo.prototype.undo = function () {
  this.done = false;
};

// the color coded mixin 
var ColourCoded = {
  setColourRGB: function (r, g, b) {
    this.colourCode = { r: r, g: g, b: b };
  },
  getColourRGB: function () {
    return this.colourCode;
  }
};

// and now we compose the mixing with the
// Todo prototype to give this color coded
// functionality to all existing Todo's

extend(Todo.prototype, ColourCoded);

And that’s a way in which you can compose objects with other objects and magically enrich them with new functionality in JavaScript. There’s more interesting stuff about this in the book so don’t hesitate to take a look.

In Concluding

And that is it, I hope that with this post you have seen a new side of JavaScript and how you can leverage its functional character to write smaller composable functions and in turn more readable, intentional, terse and reusable JavaScript.

I, myself, am going to continue reviewing all this functional mumbo jumbo on my wiki (there’s a lot of stuff about combinators, tail-call optimization, trampolining in the book that I need to get back to) and also think about how to bring all this stuff back to my C# programming.

Anyhow, I wholeheartedly recommend this book, it is very different to any other JavaScript book that I have read thus far and I think you will thoroughly enjoy its functional flavor.

Oh! One last practical thing, you may be wondering how to read the book. You can read it free on the web, buy the ebook it via LeanPub or get it for your Kindle at Amazon (but note that the kindle version hasn’t been updated to the sixth edition). Have a good one!

Notes:

[1]: Joseph Albahari’s presentation on programming with purity in YOW Australia 2013 where he talks about how to write more functional C# and the benefits you can reap from doing so.

Comments