Javascript is really really fluid and gives you many ways to express yourself:

Objects

Functions

Higher-order functions

Closures

Classes

Instances

Modules

So with all of this freedom, where do you even begin? When should you use a class instead of a collection of functions? When is a higher order function more appropriate than a class? Let’s explore :)

Program for people

The number one guiding principle I follow is program for people, especially the most important person: me! I’m sure if you’ve worked on a project for longer than that you’ve had an experience like:

Open file.* Omg, what idiot wrote this. *git blame* …

It was me.

This humbling experience leads to all sorts of good programming practices, like intermediate variables, terse comments, and, the subject of this article, grouping primitives into higher-level abstractions.

When you program in well-tested higher-level abstractions, you can deal with a problem on the domain level, rather than at the algorithmic level. I’m dealing with a User, not a collection of pure functions.

I like to use the simplest possible expression to express the problem at the highest level of abstraction.

Objects

Objects are generally good for storing data. The problem is that they’re loosely typed. Without strict typing, you can’t express the problem at a higher level.

Strict typing is the foundation of abstraction.

And abstraction lets you compensate for the limited size of your skull by allowing you to reason about a problem at different levels.

SO, you need to use either a function or a class to enforce an object’s type and structure.

Functions

You can use a pure function to enforce type. This is basically what redux does, with its reducers. Redux is extremely interesting to me because functions are essentially used to store data. The problem I have with it is you can’t assume the structure of an object you get from a function, which leads to a duplication of type-checking. Type-checking, again, is the foundation of abstraction, useful for reducing cognitive load and getting more shit done.

So, I can describe a user as a function:

userValidator = ({ username }) => ({ /* user stuff */ })

Then when I want to map that to a persistence layer (like a database) with a DataMapper pattern, I’d create another function

createUser = user => sql(‘INSERT’)

And then you’d use it like:

createUser(userValidator({ username: ‘tucker’ }))

But there’s no way to ensure the object passed to createUser has a valid structure, so you’d have to duplicate your type-checking efforts in createUser().

We’ll get to fixing this in a bit, but first let’s look at another problem: the `sql` dependency is hidden within the module, not injected, so it’s not easily testable. Dependency injection is the bedrock of testability. You’d dependency-inject it in functional programming with a higher-order function.

Higher-order functions

Higher-order functions are useful for customizing a function for a particular use. In particular, for injecting dependencies.

We can rewrite createUser using a higher-order function like:

createUser = sql => user => sql('INSERT')

That way you could re-use the sql instance, and define it’s connection parameters in one place without using globals: