“In physics, a state of matter is one of the distinct forms in which matter can exist. Four states of matter are observable in everyday life: solid, liquid, gas, and plasma.”

No matter the field of knowledge, a state is defined by :

some intrinsic properties (shape, color, weight, …)

the values of those properties at a give time

the condition of its existence and the rules that drive its mutation

If we refer to computer science, we all learned how a state machine works. I find its definition pretty great and it brings some very good insights about what’s coming next in this post:

It is an abstract machine that can be in exactly one of a finite number of states at any given time. The state machine can change from one state to another in response to some external inputs. The change from one state to another is called a transition. An state machine is defined by a list of its states, its initial state, and the conditions for each transition.

Guess what ? An application is a state machine:

a state for an application is the agregat of: its screens layouts, the navigation between those screens, the data it displays, the sounds it can emit, …

it has a finite number of possible states

it can only be in one state at a time depending on user inputs, runtime environment, physical device, external data, …

according to external inputs (user, network, …), an application will go from a state to another (navigation between screens, view update, …): these are state transitions.

State is the heart of your application, by definition !

If State is correctly handled, you are on a good path to have a safe, bug free application.

State Container Architectures

Mastering the notion of state is only the first half of the way 😀. The challenge is to handle it well. This is where “State Container Architectures” come into play.

State Container Architectures are not a brand new idea, they all rely on well known concepts such as value types, immutability, functional programming and unidirectional data flow. Redux is a famous implementation of this kind of architecture.

Before going further, I strongly encourage you to read these 2 great articles about state container and unidirectional data flow architectures:

A picture worth a thousand words

The only purpose of a State Container Architecture is to provide a safe way to mutate and expose the state within your application. Here is the flow of such a pattern:

State container unidirectional data flow

The first thing to notice here is the unidirectional aspect of the flow: you can imagine a loop of events coming from and going back to the view and producing a new version of the state at each iteration. This is our state transitions from the previous state machine definition.

A glance at each concept of this pattern

The Store is the component that handles your State . It has only one input: a “ dispatch() ” function, that takes an Action as a parameter.

is the component that handles your . It has only one input: a “ ” function, that takes an as a parameter. The State must be immutable by definition. The only way to trigger a State mutation is to call the Store ’s “ dispatch() ” function with an Action , it will create a new State .

must be immutable by definition. The only way to trigger a mutation is to call the ’s “ ” function with an , it will create a new . Actions are simple types with no business logic (structs for instance). They embed the payload needed to mutate the State (ids, search strings, …).

are simple types with no business logic (structs for instance). They embed the payload needed to mutate the (ids, search strings, …). Only pure and testable functions called Reducers can mutate a State . A “ reduce() ” function takes a State , an Action and returns the new State … that simple (this is the State transition).

can mutate a . A “ ” function takes a , an and returns the new … that simple (this is the transition). You can have as many Reducers as you want, they will be applied by the Store ’s “ dispatch() ” function sequentially. It could be nice to have a Reducer per business concern for instance.

as you want, they will be applied by the ’s “ ” function sequentially. It could be nice to have a per business concern for instance. Reducers cannot perform asynchronous logic, they can only mutate the State in a synchronous and testable way. Asynchronous work, being side effects, will be taken care of by other mechanisms (we will see that in the second part of this article).

cannot perform asynchronous logic, they can only mutate the in a synchronous and testable way. Asynchronous work, being side effects, will be taken care of by other mechanisms (we will see that in the second part of this article). The Store exposes some kind of State observable so that your views can be notified each time a new State is calculated.

Why is this a nice pattern ?

As we saw earlier: “State is the heart of your application, by definition !”. Having a reproductible, safe, state centric pattern brings some nice garanties:

No uncontrolled propagation for the State modifications. As it is a value type, each mutation creates a new copy of the State . It is not a shared reference type which mutations could lead to inconsistency all across the application.

modifications. As it is a value type, each mutation creates a new copy of the . It is not a shared reference type which mutations could lead to inconsistency all across the application. State mutation is very strictly framed by Actions dispatching. This provides a very safe environment to onboard new players in your development team.

mutation is very strictly framed by dispatching. This provides a very safe environment to onboard new players in your development team. Race conditions are avoided thanks to State being a value type and asynchronous works being very segregated.

being a value type and asynchronous works being very segregated. Application global State is extremely reproducible. It is an undeniable benefit of State being centralized within a Store . We can serialize it, save it on the filesystem and replay it at will. The application will be restored in a similar configuration each time.

is extremely reproducible. It is an undeniable benefit of being centralized within a . We can serialize it, save it on the filesystem and replay it at will. The application will be restored in a similar configuration each time. Not only State mutations are reproducible but also very testable because they are induced by pure functions free from side effects. All we have to test is Reducers’ outputs consistency given a stable input.

I find this approach very interesting compared to the more traditional patterns, because it takes care of the consistency of your application state. MVC, MVP, MVVM or VIPER help you slice your application into well defined layers but they don’t guide you so much when it comes to handle the state of your app.

That’s it for the first part of this topic. We’ve learned a lot about the basics of State Container Architectures. In part 2, we will dive in a Reactive implementation called RxReduce that will help you handle the state, its mutations and the asynchronous work related to the side effects.

Stay tuned.