Readers' Questions - "Are there any plans for Ember Data to embrace immutability?"

Hello once again to Readers’ Questions, presented by the Ember.js Times folks, with a little help from the core teams :slight_smile:

Today we have a question by rmmmp regarding the future of Ember Data:

Immutability seems to be the story with Glimmer going forward. Are there any plans yet for Ember Data to embrace this?

‐ rmmmp

Our answer comes once again from @dgeb. Buckle in, this one is a long ride!

Yes, there are plans! Before I get into details, I should unpack how embracing immutability can bring clarity and efficiency to different layers of an application.

Ember developers are already familiar with the “Data Down Actions Up” (DDAU) pattern for modeling application flow. Using this pattern, requests to change data (“actions”) are sent up to the parent component, and the resulting changes flow back down from the parent component.

This approach works well with immutable data today, since any data sent upstream can be distinct from data that flows downstream. This approach stands in contrast with the two-way binding pattern originally used by Ember applications, which intrinsically linked the data together.

Since the addition of Glimmer in Ember 1.13, you can efficiently replace entire arrays deeply in a parent component, and use the key= argument to #each to efficiently re-render. If you’re familiar with React’s philosophy on immutability, you can see that Ember’s component layer encourages the same point of view.

For the curious, the main difference is that you only need to use keys in Ember for loops, and never for conditionals, because the placement of conditionals is static in Glimmer.

As you alluded to, Glimmer takes this a step further and assumes immutability by default. A component’s properties will only be expected to mutate when they have been decorated as @tracked. Requiring this explicit signaling of mutable state allows Glimmer to track component state as efficiently as possible, which in turn makes rendering (and re-rendering) quite performant.

Immutability can also bring some distinct advantages to the data layer. To understand these advantages, it’s important to understand a little bit about working with immutable data structures.

First of all, immutable data structures can’t be changed in place. Once you have a reference to an immutable data structure, you can guarantee that the data associated with that reference will not change. Whole data structures, such as a collection of records, can be “cloned” by reference (i.e. let clone = original). And you can perform a strict equality (===) check between two data structures to see if their contents have changed.

So how do you change immutable data structures? You don’t! Instead you must create a brand new data structure that incorporates your changes. This process is made efficient by immutable data structures such as hash array mapped tries that are optimized for lookup and update performance.

What benefits could immutable data structures bring to Ember Data? If Ember Data’s Store used immutable data structures to store records, it would unlock the often requested feature of “store forking”. Forking has a number of different use cases based upon isolating changes to a “fork” from a “main” store: whether to allow edits in a form, or perhaps load a large but transient dataset. Forking a store by reference is almost infinitely faster than deep cloning a whole bunch of record objects. Forked stores could then diverge from their parent, and changes made to the fork could eventually be merged back to the parent or abandoned. The equality of the contents of two stores could always be compared with a simple strict equality check on the immutable data structure(s) holding their records.

Another benefit that immutable data structures could bring to Ember Data is control over record mutations. Since immutable changes must always be made by structure-aware operators, Ember Data’s Store and Model classes could effectively be a gatekeeper to any mutation made to a store’s records. And if mutations are managed by a gatekeeper, they can also be tracked. And by tracking changes, we can more deterministically reason about data as a series of operations with a history, which provides further advantages.

In order to unlock any of these changes in Ember Data, we first need to expose its current internals that are used to access data. This is the very purpose of Igor Terzic’s Model Data RFC. Formalizing this interface is the first step to implementing fundamental changes to Ember Data, including the embrace of immutable data structures. Since this RFC is in “Final Comment Period” now, it’s a good time to check it out.

Once Ember Data more fully embraces immutability, it will align quite well with the application flows already supported by Ember and Glimmer.

I’ll be talking about all of this and more in my EmberConf talk The Future of Data in Ember. Hope to see you all there in a few weeks!


This answer was published in Issue #34. Don’t forget to subscribe to the newsletter to get development news right in your inbox. You can also submit your own questions! You will find a link at the bottom of the newsletter.

See you in the next issue!