Store immutability and the freezer

Apr 20, 2016  

I’ve already blogged about Electrum (see electrum on GitHub) a few times in the past. The project is maturing and getting larger, with colleagues starting to actively contributing.

One of the sub-projects (electrum-store) implements an immutable store. The store can be pictured as a tree of nodes (the state objects). Every node can contain values and is itself a tiny immutable key/value store.

Here is a simple example:

let store = Store.create ();
let state;

state = store.select ('a.b.c');
state = state.set ('x', 10);
state = state.set ('y', {foo: 'bar'}); 

With this in place, we can read back the state:

  • state.get ('x')10
  • state.get ('y'){foo: 'bar'}

An immutable store storing mutable data

When setting an object like {foo: 'bar'} in previous example, the store itself can be considered immutable, but nothing prevents anyone to mutate the stored item:

state.get ('y').foo = 'bozo';

I don’t like the idea of users mistakenly altering the state, because this might introduce hard to locate bugs. In our case, the store is used to speed up checking for changes: components can check whether the state changed by simply doing a reference comparison and provides a very efficient implementation of React’s shouldComponentUpdate() method.

However, if a user mutates an object stored in the state, this will not be detected, and the UI won’t be refreshed.

Freezing the mutable values

In electrum-store v2.0.0, I decided to address this issue and set() now freezes the values stored in the state object. Code like this will throw an exception:

state.get ('y').foo = 'bozo'; // throw exception, object is frozen

Ideally, I’d love to have only fully immutable values (i.e. with a deep freeze, walking recursively through the property graph), but this might not be practical, because it would mean that we can no longer store complex objects in the state, without freezing the world.

So for now, set('y', {foo: zzz}) only freezes {foo: zzz} at the top level and zzz will stay unfrozen.

Freezing arrays deeply

The state may also store arrays. Setting an array on a state object will freeze the array recursively, until objects are reached.