Embracing Immutable Architecture
What is Immutable Architecture, anyways?
To understand immutable architecture, we need to first understand state. State, an evil source of complexity in any software, is the characteristic of a value. According to Miriam Webster, state is defined as “the particular condition that someone or something is in at a specific time.” As we continue to make web applications with more and more dynamic data, we are introducing more and more state into our applications.
Combined with asynchronicity, a core characteristic of modern web applications, it’s no wonder why our applications have become very hard to understand.
Whether you realize it or not, you have most definitely dealt with state bugs many times over if you are a software engineer in any capacity. In fact, there is a famous white-paper about the Software Crisis that references state as the number one contributor to software complexity.
The main issue with state complexity is that it causes our code to become harder to reason about. When you are unable to reason about what your code is doing, you lose the ability to properly communicate with the computer and that leads to bugs and the inability to maintain the software. As software scales to more and more people, the probability of introducing state bugs increases exponentially.
So how do we control state complexity? It’s actually really simple, we use Immutability to our advantage.
Immutability is defined as “unchanging over time or unable to be changed.” In software, a value that is immutable, by its very definition, does not have state! With one simple change, our entire problem is solved! Where the complexity sinks back in is when you try to do anything meaningful without stateful data and the ability to mutate data.
It is a common misconception that immutability hinders the engineer’s ability to write meaningful software. Without going into the details of the mathematical background of Functional Programming, I am going to attempt to explain immutable architecture in simple terms that hopefully all of us can understand.
In the case of Redux, we use pure functions to mutate state. Pure functions are defined as those that given the same input, always return the same output. In other words, they are predictable as they do not rely on any outside mechanism or global state.
By employing state management in our apps, we are boldly turning off mutable state within the majority of our app and we are using state management to manage the situations where our state needs to be changed in order to provide a meaningful experience to our application’s end users.
I hope you see that this idea is fundamentally simplistic in nature. You do not need to be a functional programming wizard to understand it. State management needs to be a primary focus of all of our applications going forwards.
One way data flow
I am sure you have no doubt heard of unidirectional data flow by now. It is a natural extension of the ideas described above. With unidirectional data flow, we take the principles of pure functions and apply it to our entire app.
So now, our state is managed properly, we are using immutability throughout our app and our application consists almost entirely of pure functions. By thinking of our applications as a pure function of state, we are suddenly able to reason about what the application is doing. This can be applied to our entire application architecture, from data-fetching to UI.
A perfect example of this in practice is React. With React, you design your user interface as a collection of components. Each component is a pure function that takes data and returns HTML. With unidirectional data flow, we are able to describe our application as pure functions and we are given the guarantee that when the data changes in our app, through a predictable state management mechanism of course, the user interface will be completely recalculated.
Suddenly, we are given a guarantee that if our UI renders correctly once, it will render the same from now until eternity. The components of your application are now totally decoupled from the complexity of your app. This makes testing, both manual and automated, a predictable process.
The transition to Immutable architecture represents a paradigm shift in our industry. Those of us that are using Immutable architecture on a daily basis are here to stay. Our software development process is just so much easier and less buggy. It scales well because it eliminates the biggest cause of software complexity, which again is the complexity caused by mutative state.
If you have yet to embrace immutable architecture, I recommend the following resources.
- Talk by Lee Byron on Immutable Architecture
- Motivation behind Redux
- Mostly Adequate Guide to Functional Programming in JS
- Purely Functional Data Structures— Not for the feingt of heart, but a fantastic source of information about persistant immutable data structures.
- Immutable Infrastructure in Cloud Computing
Please click the like button if you enjoyed this!