Immutability to Remain Unchanged


One of the cornerstones of Functional Programming is the idea of immutability. Although frequently misconstrued, Immutability is simply the concept that once we set a value, that object or variable will not change. Once we set that value, any attempts to change it will create a new object. It seems like a simple concept but its extremely powerful. Before we dive into immutability and what it provides, lets look at the standard.

Mutability, and how its always been.

When most engineers are introduced to the concept of immutability they get a certain look on their face as if you just told them the sky was really green. The idea that you cannot change something seems so rigid and backwards. Like most engineers when I started with OOP I too learned of mutability, that I could change a variable, reuse it, and let it morph over the lifecycle of my application. It seemed to me obvious that, thats what I wanted. But as I spent more time building larger applications, I saw the inherent problem, or rather someone showed me it.

With mutability we have very little certainty of the state of our application. If we can change a variable, that means anyone with access to the codebase can. In Javascript we don’t even know if the type, string object etc, is consistent with the new variable replacing it. So much of our time as developers is spent tracking down whether a value is what we expect it to be.

As more functions interact with a value it becomes increasingly harder to be certain that our object is what we expect it to be. You’d think this would be a highly talked about issue but the moment we learn computer programming we’re all shown that there’s only one way, mutability. It's like a stockholm syndrome where we're so used to a certain paradigm, that Immutable seems too foreign. Whether you get a degree, go to a bootcamp or teach yourself, the general approach taught is mutable objects.

Take the example below, are we certain what will output from drone.engine. How do we know that drone.egine hasn’t changed? Sure we could go and check droneFactory and figure out what mutations have happened. To really create something large and scalable we can’t hold all this minutiae in our head.

function updateDrone (droneFactory) { 
   var drone = {engine: "X3000"}
   droneFactory(drone);
   console.log(drone.engine);
}; 

Mutability makes us focus on the wrong part of programming. Instead of concerning ourselves with composing stable modules that can scale we are forced to focus on state changes. With Immutability state changes is removed as a concern.

Issues with Immutability

At this point one might think that Immutability is a godsend, it is, and that it’s perfect. But like most things in programming its a case of trade offs. With Immutability our trade off is that while we have more certainty with our app, we also use more memory. Think instead of replacing existing values in memory we’re creating entirely new ones and repointing our variables. This is certainly a costly process for our garbage collection. In fact this very point is what has held immutability as largely an academic topic instead of a mainstay of computer programming for over twenty years, until Okasaki.

Okasaki was like many pioneers a grad student desperately trying to finish his thesis. While he was well versed in functional data structures, he knew there was a way to make them faster.
The big breakthrough with making immutable structures practical Structural Sharing, the idea of immutable structures sharing older structures tree, had already been created. But Okasaki new there was much work to do to make them optimal. He described his breakthrough as such.

"The whole way home I thought about nothing but how to analyze my data structure. I knew it had something to do with amortization, but the usual techniques weren't working. About halfway home, I came up with the idea of using debits instead of credits, and by the time I got home the entire framework of how to analyze data structures involving lazy evaluation had crystallized in my head. "

We won’t go into different types of functional data structures and lazy evaluation in this piece. We’ll save Okasaki and functional structures for a later time when we have more familiarity with functional programming. But a note to self, take more long walks there seems to be something behind that.

The concepts we really need to appreciate at this point with Immutable data structures is the fact that they provide certainty within our applications. Where before we had mutability and frequent unstructured changes we’ve replaced it with static objects.

How to Integrate

By now you should have a solid understanding of the differences between Immutability and Mutable objects. So lets get to the exciting part of actually integrating it. The main library I’ve experimented with for client side immutability has been Immutable JS from Facebook. If you’re like most people you’ll be working on a codebase with more than just you as the developer and if thats the case you’ll need to take different approaches.

For greenfield projects we can do the best solution which is to change data at the lower level closest to the API. Any gets and details call should be changed to Immutable data. For posts and puts we should setup a converter to change back to Javascript objects.

function getItems(data) { 
var immutableData = Immutable.fromJS(data);
return data;
    //// http get call 
};

function postItem(data) { 
var objType = Immutable.Iterable.isIterable(data), 
modifiedData; 

if(objType) {
        var modifiedData = Immutable.toJS(data); 
    }
   /// http post call
 };

When we’re not working with greenfield projects we have to be more careful with how we’re using Immutability. There are going to be existing parts of the app, reliant on mutable data structures. We’ll need to change objects to Immutable and also create a parser to convert them back for areas of the codebase outside of our domain.

// Change to Mutable 
 function toMutable (input) { 
   var modifiedInput =  (Immutable.Iterable.isIterable(input)) ? input.toJS() : input;
   return modifiedInput;
};

// Change to Immutable
Immutable.fromJS(input); 

If we’re working with other parts of the application that have mutable data structures the best approach is to use it in an isolated component. I’ve linked to a sample codebase that includes an immutable and mutable version. Take a look at the table to get an idea of how to integrate it into the codebase.

We have enough knowledge to go ahead and integrate it into our codebases. If you need a small step check out this simple assignment.

In the future I’ll be doing an advanced piece crystallizing functional data structures and Osaki. But until then happy coding!

This is the second piece in a series The Functional Programmer's Starter Kit. This guide details how to come from a novice to implementing functional programming into your codebase.

HD