Member preview

Immutability — No Mutants Allowed

Add, remove, or change object properties… and the mutants will start pouring down the escape hatch. What? Well…

Click here to share this article on LinkedIn »

You can find my react.js book on Amazon here. Support is appreciated. -jst

Immutability preserves structure and values of your variables or object properties. It’s a hodgepodge between a particular style of programming that helps reduce errors in your code and elitism tendencies that follow after successful execution of the former!

At its basic The Immutability Principle tells us not to change data types during value assignment. Wait. But… as a JavaScript coder why wouldn’t I want to change my data types when creating variables?

Isn’t that what programming is all about — juggling data around? Besides JavaScript is a weakly-typed language. By its very design it appears to easily mutate data types. It’s how we all learned it. It’s not like it’s TypeScript.

All of this is true.

But… as you hone your software engineering skills — and if you actually care about writing good code — in time you will hopefully begin to think of your program’s architecture.

Mutability – refers to changing or updating data. Most of us have all done that without knowing by simply fiddling with objects’ properties. To what end? Hundreds of type-mismatch errors per day in the Chrome console.

Immutability – a principle that does not allow changes to data. Immutable code is usually characterized by following:

1. Less side-effects: a side-effect is when a function changes data outside of its own scope. The concept of a pure function is based around this logic.
2. Function purity: produces easier to test code because the result of a pure function is predictable and doesn’t depend on outside scope.

Think of pure functions as little containers that always produce predictable results. Here is an example of the simplest pure function in JavaScript.

// Pure function that returns a sum of two arguments:
function sum(a, b) { return a + b; }

There is a bit of irony in showing you this example.

In languages like JavaScript — that were not originally designed with immutability in mind — there are different degrees of purity.

For this reason in practice not in principle this function can potentially still be considered impure because if you pass an Array to it (instead of Number) it will produce side-effects.

You can make a wild uneducated guess and say this function is 80% pure in practice. Or you can even go as far as to say it is only 50% pure… if you consider all possible types of data that can be passed to it, not just Arrays.

JavaScript originally was never meant to support immutability.

And so… for this reason one must exercise a certain degree of caution when it comes to reducing side effects in your application.

Side Effects

A side effect is an unwanted result that often ends up generating an error. It’s often caused by using code in an unintended way.

It’s lack – or complete absence – of design in your code.

In this case, even though conceptually the function is pure, side effects are still possible largely due to the design of JavaScript language. But it can be avoided in part due to the choices made by the programmer herself.

Of course if you’re fiddling with ES6+ you can also use strong types in function arguments because you’re probably already using Babel to transpile from TypeScript anyway.

Still… purity is more of a principle than a language feature. It exists in other statically typed languages like C++ for example. But if you want to you can habitually stick to immutability in any of them.

Tricky part is that in C++ if a wrong type is passed to a pure function that expects a strong type the error will occur not at runtime but at compile time. You still have to deal with immutability in any language.

In contrast — an impure function.

// Variable count defined outside of inc's scope:
var count = 0;
// inc() is impure because it changes count outside its scope
function inc(v) { count += v; }

How many times have you done something like that?

Avoid mutants if necessary – It’s challenging, but it’s well worth the effort.

The deeper you get into coding the more interesting and fun it becomes.

But what else does immutability give us?

In corporate environment you will be building large-scale applications. This makes performance important. Just like what code-reuse does to the application size immutability is often pursued by those who care about faster code execution and easier testability. But it comes at expense of sticking to rules. And nobody likes rules. You might have to get used to it.

Immutability can apply to overall coding practice, not just pure functions.

In fact, immutability can be achieved even in a weakly-typed language by simply making a promise to yourself that you will not mutate your data whenever possible and if it achieves performance gain. Which makes it not merely a language feature but a personal design choice. And a good one at that. I am rooting for you to start using it!

Think of a pure function for example. It’s a type of a function whose arguments do not change throughout its execution cycle. The result of an immutable function is always certain provided the supplied arguments don’t change. They are predictable. And that means — easier to test.

Where else in JavaScript we can see immutability?

You can use const keyword to create static variables or properties. And Object.freeze() method can provide immutability for object properties.

A note from Mozilla documentation: The Object.freeze() method freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed, it also prevents the prototype from being changed. The method returns the object in a frozen state.

Planning your application in such way where object properties do not change (at least not directly) is more of a habit rather than dependency on a specific reserved keyword or language feature.

React Programming and Immutability

React does not limit you to using either mutable or immutable data.

React lets you use whatever style of data management you want, including mutation. However, if you can use immutable data in performance-critical parts of your application it’s easy to implement shouldComponentUpdate() method to significantly speed up your app.

Dealing with immutable data in JavaScript is more difficult than in languages designed for it, like Clojure. However, React provides a simple immutability helper called update() that makes dealing with immutable data much easier without fundamentally changing data representation.

And on this note… it seems like our little tour de force around immutability has come to an end. Just remember…

When it comes to immutable design — Mutants Are Not Allowed. Nuff said.

Follow me on GitHub, if interested — I follow back :-)