Clean Architecture – Chapter 6 | Functional Programming

To explain Functional Programming, the author uses an example of square of numbers written in clojure (derivative of lisp)

(println (take 25 (map (fn [x] (* c c) ) (range))))

Let’s break it down to understand it as I am also new to this language. In clojure everything in brackets is a function. Starting from inner most function the execution would be something like this – 

  1. Range function returns a never-ending list of integers.
  2. The list is passed to map function, which calls the square function on each integer in the never-ending list of integers
  3. This never ending list of squared integers is passed to take function which returns new list with only first 25 elements
  4. println function prints the list of 25 elements

Let’s see how the same program would look in Java

for(int num = 1; num <= 25; num++)
{
      int square = num * num;
      System.out.println(num);
}

The difference between Java and Clojure is – 

  1. In Java there is a mutable variable num whose value changes stare with execution
  2. In Clojure, there is no mutable variable. The value of variable x is initialized but never modified. In functional programming, variables don’t vary. They are immutable.

What’s the importance of immutability when it comes to architecture? 

Ans – All race conditions, deadlock conditions, and concurrent update problems happen because of mutable variables. Think, if. there is no variable to update there will be no concurrent update problem. All these will go away if we have processes that work on immutable variables.

The author asks architects to ask themselves this question – Is immutability practicable?

His ans – Yes, immutability is practicable, but with certain compromises. 

First compromise is that we need to segregate system into components that are mutable and immutable. The immutable components will be implemented using functional programming and use immutable variables. They can talk with the mutable components and allow for state of variables be mutated. This does expose the components to problems of concurrency and it is common to use some sort of transactional memory to protect the mutable variable against race conditions and concurrent updates. Architects must try to move as much processing as possible in to immutable components.

Second compromise is Event sourcing. It is a strategy wherein we store transactions, but not state. When state is needed, we apply all transactions from the beginning of state. 

Consider the example of banks. They maintain account balances of millions of customers. It mutates those balances when the withdrawal and deposits are made. Say, instead of mutating the account balances, we store only the deposit and withdrawal transactions. And when required, we create the account balance using the transactions from start of account creation. This approach doesn’t need the mutable variables. 

Yes, it would need lot of memory and processing power to maintain the numerous transactions and compute the balance when needed. This could be optimized, like we store state everyday at midnight. So if anyone wants account balance next day, we would just need to compute transactions starting from midnight. 

In this approach we are storing transactions, so nothing ever gets updated or deleted from our data store. This makes the data store CR instead of CRUD. No deletion/updation and so no concurrent update problem.

With the advancement of computer technology, now we have enough memory and processing power that this immutablility can be achieved. 

To nail his point on benefits of functional programming and immutable variables, he gives the example of our source code control system. 

Thanks for stopping by. Hope this gives a summary of functional programming. Eager to hear your thoughts and chat, please leave comments below and we can discuss.