Coffee Shop is a great example demonstrating the benefits of Functional Programming.

Functional Programming (FP) is based on a simple idea of constructing programs using pure functions. A pure function returns the same value for the same arguments, its evaluation has no side effects (i.e. no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams). A simple example of a pure function in JavaScript could be map, filter and reduce methods defined on a prototype of Array data structure.

Let’s look at an example to demonstrate the benefits of FP and pure functions.

Coffee Shop

Suppose, we’re implementing a program to handle purchases at a coffee shop. I’ll start with a simple program with side effects and then rewrite it with pure functions. Domain entities are different kinds of coffee with corresponding prices (Fig. 1) and credit cards to pay for a given order (Fig. 2).

Fig. 1. Base Coffee interface, Late and Cappuccino implementations.

Fig. 2. Credit card provides an async method “charge()” to execute an order for a given price. For the sake of simplicity it returns a promise of nothing “void”.

A naive implementation of the Coffee Shop App should allow to choose a type of coffee and place an order (Fig. 3).

Fig. 3. Customers can buy a cup of coffee.

In this implementation, the LINE #28 cc.charge(cup.price) is an example of a side effect, because charging a credit card involves some interactions with the outside world.

Assume that there are two clients: Alice and Bob. Alice placed an order for a cup of Latte and Cappuccino, Bob — just Latte.

Fig. 4. Customers placed orders.

Probably there are more customers and some of them want to order 12 cups of coffee. As it currently implemented, that will involve 12 individual calls to a payment system that could add higher processing fee and operate slower. It seems to be a good idea to combine the orders belonging to the same credit card into one single transaction. What can we do about it?

Coffee Shop 2

The FP solution is to eliminate side effects. We need to make the buyCoffee() a pure function. It can be done by introducing another object called Charge that will encapsulate information about a credit card and an order price.

Fig. 5. Charge object incapsulates credit card and order price.

Instead of executing an order right away we return a tuple of the order and payment information (Fig. 6).

Fig. 6. A tuple [Coffee, Charge] is returned.

Now it’s possible to place multiple orders with different payment methods, combine those orders (Fig. 7) and execute in a single transaction per credit card (Fig. 8).

Fig. 7. Combining orders by credit card. The underscore variable is a “lodash” library.

Fig. 8. Placing orders, combining and executing.

We are now able to compose orders and apply different payment strategies because the Coffee Shop doesn’t need to know about payment processing. Overall, the solution is much flexible.