ExploreOurteamtrainingCourses (3)

Immutability – the idea that you should never work with “live” data, is slowly transforming the way that programmers work with objects, data and streams. From reducing hidden variables in functions to making database programming simpler to reducing the chance for difficult to find bugs to make its way into your code, immutability is becoming the quiet revolution in Javascript.

This particular piece is going to dig into what immutability actually means in programming (specifically in JavaScript, and even more specifically the React library). There’s more than a bit of theory here, but the goal is to illustrate why immutability – as a design pattern and a library – can make such a big difference in code.

Javascript’s Reference Problem

When most neophyte programmers are learning about functions, at some point they discover that objects can be passed as parameters. It’s perhaps at this point that the true nature of objects begin to manifest. An object can be passed by value, in which case, when you supply the object, the system creates a duplicate of that object, or it can be passed by reference.  Passing by reference means that if you change the object within the function, you are actually modifying the original object, not a duplicate.

Javascript in general dispenses with passing by value for anything except for pre-existing data types such as strings – everything is passed by reference. This can have some interesting consequences. For instance, suppose that you have an array of colors within a variable, then use the invoke a function to an item to that list at the end.

The problem with this is that if you look at both variables afterwards, you’ll discover that they contain the same list:

More experienced programmers understand that, because the colors array was passed (implicitly) by reference, the original array was modified and then passed back. Indeed, in order for the function to pass back a distinct array, it’s necessary to create a copy of the existing array then modify that:

The advantage to working by reference is that it avoids the allocation of a new object. However, there are some significant disadvantages to it, disadvantages that become more evident the more complex a project becomes. One of the biggest is that when you pass objects by reference into a function, you do not necessarily know what that function is going to do with your data. It could add additional data, remove data, rearrange information, perhaps even assign something altogether different. It’s like taking in a cat to the vet to get her claws clipped, only to get a St. Bernard (with clipped claws, mind you) when you pick her up.

This problem is frequently referred to as the hidden variables (or side effects) problem, and it can prove fiendishly difficult to debug when it happens, especially in this day and age of extended frameworks. Side-effect-free programming means that nothing can be passed by reference, and the result of a function should be free of previous references.

This approach to programming has some interesting implications. First, it means that such functions are considered composable – the output of one function can be used as the input of another, and any large action can be then broken down into a sequence of smaller functions.

Indeed, computer science identifies such programming as being functional (made up of composable functions) rather than imperative (command oriented). Javascript has been heavily influenced in the last year by concepts from functional languages such as Lisp, Scheme, Haskell, Miranda, and OCaml, as well as more recent languages such as Clojure and F#. Indeed, many of the more widely used EcmaScript 6 features, such as arrow functions, and destructuring, come directly from languages such as Haskell.

Immutables and Passing By Value

Because Javascript doesn’t have a “pass by value” parameter mode for objects, it’s necessary to circumvent the natural behavior of Javascript. To make this happen a number of libraries have sprung up around the notion of immutability, with the dominant one (and the one covered here) being immutable.js produced by the Facebook team.

Immutability implies changelessness (“mutate”, of course, means “to change”). A variable that is completely immutable, however, is pretty useless, as you couldn’t assign a value to it in the first place. Here, the distinction is that, once you have assigned a certain object value to that variable, you cannot remove information … you can only add to it. What’s more, what gets returned is a distinct object.

For instance (assuming you’ve added the appropriate library), the immutable List object gives you similar functionality to the Array object:

Note that while List.push() has a similar effect to what Array.push() does (though it returns a new list), List.pop() returns a new list copying the old one, but removing the last item. This means that you need to retrieve the end of the list first (the thing being popped off) before calling the list.pop() function.

The Immutable.js library incorporates a number of related data structures – Lists, Sets, Maps, Ordered Maps, Stacks, Ranges, Sequences (Seq), Records and Iterables, along with the abstract Collection structure that underlies the others. Most of these have been optimized to provide the minimum necessary storage for the types. For instance, you can set a range (a sequence of consecutive numbers) to have an infinite number of items. These range object doesn’t actually store this (for obvious reasons), but instead provides an iterator function that produces new items with the appropriate value when needed.

It should be noted that ES6 does not have native immutables, though classes can be built that provide this functionality. Whether immutables will make it into a subsequent version of Javascript natively is still being determined.

React’s Immutables and Efficient Processing

One of the key benefits of MVC frameworks is the concept of data binding – a variable (or data in general) is bound by a user interface controller to a specific presentation view. By changing the data you change the view and vice versa. While React is not a full MVC (it only handles the view layer), internally React maintains a virtual DOM that is optimized to determine whether a given subcomponent needs to be refreshed. Put another way, React doesn’t bind user interface controls directly, but instead re-renders subcomponents when its internal model changes.

As such, immutability can play a major role in React – and in fact can vastly improve performance there. To understand why, a couple of diagrams can prove useful:

Diagram 1. React components with mutable deep source JSON.

In Diagram 1, a React component updates up to three levels deep. Each “node” is a DOM node that is created in memory, then compared to what is already there. If the calculated DOM output is the same as what’s there, that node is not updated, but any child components still must go through this same process. This means that, here, React has to look at 12 of 15 nodes, and change roughly half, avoiding the final three only because the data for generating the need is a leaf and hence either changed or unchanged for all children.

The key to making this happen is the shouldComponentUpdate() method of the React class, which returns true if the component needs to be updated and false otherwise. The React base class has it’s own sCU() function, but by writing a new one you overwrite this for those components where such comparisons take place.

Diagram 2. React component with immutable data.

In the case where data structures are guaranteed immutable, there are two comparisons – the first is, as above, whether the pre-rendered DOM structures have changed, while the latter indicates whether the source data itself has changed. Once React has a guarantee that a deep source data structure is the same all the way down, then this can shortcut the need to check every node.

This means that, in the above case, rather than needing to check 80% of the nodes, you only need to check 45%, and only need to change 4. The can result in huge performance differences, especially for complex renders.

Immutability makes this process a little more difficult in some respects, though easier in others. In a mutable framework, you need to place observers on variables in order to determine when a specific value has changed, then you have to navigate to the view to modify just that particular value. This means that you end up with a great number of dependencies, that often have an adverse impact upon performance.

With immutability, on the other hand, you do not need to know precisely what changed. This means that when you update a specific instance in your model at any point, you are changing the whole instance. By binding to the instance rather than a specific value in that instance, the component in question would then just update the visual appearance of the whole component. This can make for a slightly less granular design, but has no hidden variables, and more to the point becomes recursively composable – you only modify things that are specifically in the context of the component, not the framework that the component is in. You also have the advantage of being able to archive the old state in toto for that component, possibly associating it with a time stamp. This makes “undos” much easier.

Using React, you can add support for immutables by requiring the “react-addons-update.js” library from the React site.

The following shows how such immutables may be changed in React, with the update() function handling the process of creating a new immutable from an existing one.

The notation {$apply: (x) => x*x} is an example of a command, and includes $apply, $set, $push, $unshift, $splice and $merge, the dominant mutation commands. More information about immutables in React can be found at https://facebook.github.io/react/docs/update.html.

An Immutable React Example: Image Viewer

One of the best ways of understanding immutables is to see a working example. The following is a React component that allows users to enter in URLS of pictures, see a preview, then add this to an image carousel of thumbnails. When you click on a thumbnail, the larger image is displayed, as shown below.


JS Bin on jsbin.com

While the application is a comparatively simple one, it does illustrate one way that React makes use of immutable data structures. The code for the image viewer can be seen below:


The results of this code can be seen and explored with at  http://output.jsbin.com/zonihem.

The Benefits of Immutables

Preventing corruption by ensuring that existing data can’t be overwritten is one area where immutables provide useful. There are others. One such, as a design principle, comes in separating the data of an object from its operations. This may seem more than a little counterintuitive. After all, isn’t one of the biggest benefits of object oriented programming the fact that you can in fact encapsulate (or bundle) data together with its operations?

The answer may surprise you. Object oriented programming arose at a time when most applications were stand-alone, and the number of objects in play were typically fairly small. The benefit of retaining state was also fairly small for many of these objects, so you could effectively update the state of an object by overwriting the previous state, without worrying about retaining previous information.

That began to change as applications began to span tiers. Increasingly, data structures have resided in documents, either JSON or (less commonly) XML, located on servers. In this case the Javascript acts like a function to modify the document as a unit, then update this back to the server.

This idea of treating data contextually – not just single values but essentially all of the local information about a given entity – has a profound impact on development. Most information is not atomic – you seldom change a street address without changing city, state and zipcode. In an immutable world, this entity becomes, in essence, a key part of a transaction, and the transaction is only committed once the information it contains is complete and internally consistent. As such, working on copies of things only makes sense, and functions should then be seen as things that can change the entity as a whole.

Immutables carry this concept into the core of coding, reminding you as the coder that you are working not on individual properties (or even records) but objects as a whole. As such the use of immutability prevents incomplete (or improper) transactions, enables better code pipelines and prevents unexpected side effects that can add significantly to the debugging cycle cost and time.

Kurt Cagle (kurt.cagle@gmail.com) is an author, information architect and Javascript programmer. He is available for Javascript, node, MarkLogic and semantic software development.

Kurt Cagle
Kurt Cagle (kurt.cagle@gmail.com) is an author of twenty books, blogger, and software architect, and is available for consulting or hire. He lives in Issaquah, WA with his wife, daughters, and cat.
es6, Immutable, React