Hackernoon logoImmutability? that is the question! by@pedro.barros

Immutability? that is the question!

Author profile picture

@pedro.barrosPedro Barros

Immutability? that is the question!

Functional Programming tends to scare people with the academic terms borrowed from Category Theory to describe interfaces known as “Algebraic Structures”.

Functional Paradigm was adopted through languages like Erlang, R and even the most recent ML, Haskell, OCaml, F # and Elixir. Already our beloved Javascript wasn’t designed to be a functional language. Fortunately, JavaScript is well-suited for the task, thanks to first-class, high-order functions and proper tail-call optimization provided in ES2015.

The more abstract a concept is, the harder it is to understand. Interfaces are abstract in nature. The more abstract they are, the more powerful they become, because they allow us to solve a wider range of problems apparently unrelated to a surprisingly small set of patterns.

The purpose of functional programming is to allow us to think less and write more descriptive codes.

The good news is that you don’t need to turn the key and everything is working in your head. You can apply functional approaches as you learn. I’ve been slowly studying this paradigm, and every day I see new ways of solving problems and each refactoring makes the code much more enjoyable.

Learning new programming paradigms is like learning a new instrument. After each note learned we increase our power of expression.

In my day-to-day work I use Functional Paradigm infrequently, but this foundation allows me to see problems in a different way and even to combine functional concepts with other paradigms such as Object Orientation. This has been a trend in the evolution of languages, in other other, we can unite the best of worlds. The example below in Typescript/Angular shows the union of functional concepts like map and Object Guidance concepts like the use of classes.

Multiple paradigms help you apply different ways of thinking about solutions to problems because solutions vary across languages.

Ultimately we will see that a stateless application is useless. But we always need to carefully select the points in the code where we allow the mutation to occur. Most of the internal parts of the code should strive to be immutable and therefore testable. The more mutations you can eliminate, the better.

Why should we care about immutability?

Chip makers are on the atomic limits of transistor miniaturization. As a result, clock rates have not increased since 2004.

Multi-core is currently the preferred strategy for improving speed. Routines with shared mutable state cannot be distributed in parallel across multiple cores because they are not thread-safe.

As a suggestion follows Robert Martin’s lecture about this subject. 
Just note: an “assignment statement” is totally benign a “reassignment statement” is problematic.

When you reassign (mutate) a variable you are introducing state change to your application. To reproduce a complex bug you often need the sequence of computations that lead to the failure. When you mutate variables you are throwing away that sequence.

How do we avoid mutations?

Whenever you need to model a state change, you pass the previous value to a function that returns a new value. Don’t change the old value just return a new one.

Manual

Although JavaScript doesn’t support immutable objects, we can still write our code in a way that avoids most mutations.

Don’t change objects in functions

Write functions that return changed copies instead of changing the properties of the specified object.

Don’t exchange objects after construction.

Objects are references, if we avoid changing their properties we avoid situations of unclear states. Also our finished code will be simpler to understand and easier to test.

It seems a lot of tedious work to avoid mutation with the above examples but the fact JavaScript doesn’t have built-in support for immutable objects makes this very difficult for us. Time to get help!

Immutable.js

Facebook’s Immutable.js is a small library that helps us keep our state immutable. There are other libraries that work in a similar way (Mori, seamless-immutable, acient-oak), but for this article we limit ourselves to Immutable.js.

Immutable.js provides many persistent immutable data structures including: List, Stack, Map, OrderedMap, Set, OrderedSet and Record

Or in form of code:

Although we lose direct access to object properties, we can now focus on our goals, rather than fighting against mutations.

ESLint Immutable

There is also the eslint-plugin-immutable plugin to disable all mutations in JavaScript. The readme mentions a lot of React/Redux, but you can safely use the plugin without both.

The plugin adds three rules:

  • no-let: use const instead of let.
  • no-this: forbids this, and therefore ES6 classes.
  • no-mutation: prohibits assigning a value to the result of member expressions.

When do we use it?

Concurrency

This is the main reason why immutability makes sense. To be thread safe, you don’t need to lock anything that is not changed. In Javascript there is no real concurrency. Instead, we have an event loop. So forget it.

To avoid side effects.

Changing object properties is considered a mutation, in other words, a side effect by definition. We all learn that we should avoid side effects at all costs. We don’t need to examine the implementation of a function if it has no side effects. Our code gets easier to reason about and will be more predictable and more testable.

With functional programming

There are times when you need to stop and think if you are dealing with a value or a reference. Immutable objects are always values. This is one of the fundamental principles of functional programming. If I pass the value to a function, I can promise that it stays the same forever.

When don’t we use it?

Often changing properties

If you have objects that change very often, it isn’t a good idea to create a new instance for each change. This is especially true for games and simulations where this happens several times per second. I’m not saying that you can’t use immutability in games, but it is easier to fall into performance problems than in mutable objects.

Huge data structures

If you have a huge data tree stored as an immutable container, I recommend checking your memory consumption. Of course, garbage collection kills all old objects, but copying large objects still has its price (Most frameworks on the market already handle this kind of problem very well).

Conclusion

In general, it is a pretty reasonable language design choice to take into consideration are the immutable types of data, since there are some problems that are simply not well modeled when everything is immutable. In most situations the advantages of immutable types vastly outweigh the disadvantages and they are better than the alternatives and lead to better code and faster executables overall.

As said at the beginning of the post, we don’t have to turn on a key to changing paradigms completely, we can start implementing immutable types gradually entering into more complex and useful patterns according to the need of our application. To end this post I leave @jamesiry’s tweet as a reflection.

Functional programmer: (noun) One who names variables “x”, names functions “f”, and names code patterns “zygohistomorphic prepromorphism” — James Iry

To be, or not to be a “Functional Programmer”, that is the question 😂

References and Related Contents

Tags

Join Hacker Noon

Create your free account to unlock your custom reading experience.