# Demystifying State Management

State management is the probably the hardest aspect of frontend and backend programming, let's demystify it using some techniques from Engineering Control Theory. 29 June 2019

## # Background

Over the years, I've had the privilege of working with many production `react`

+ `redux`

codebases across a number of industries. Most start off simple, but code complexity seemed to grow much faster than feature complexity. Much of this can be attributed to misunderstanding of how state management can/should be done. I hope this article demystifies state management for you.

## # State transition equations

In Control Theory engineering, one pair of equations is often used to describe dynamical systems :

`x[t+1] = Ax[t] + Bu[t]`

y[t ] = Cx[t]

Where it defines: `u[t]`

the input at time `t`

, `x[t]`

the state at time `t`

, `y[t]`

the output at time `t`

, and `A`

, `B`

, and `C`

the relevant transformation functions. Control Theory goes on to explore concepts of controllability and observability , and more, but we won't go that far in this article. Suffice to say, that there is a whole field of study behind this pair of equations.

Let's see what we can learn from it.

## # A classic: the todo app

Consider the classic programming challenge — the todo-app. Its inputs `u[t]`

may be a form input, an XHR response, or a push notification. These inputs may not be in a consistent or desired format, and needs to be normalised before it can be stored as local state `x[t]`

, say an array of todo items. Therefore, the next state `x[t+1]`

is a transformation `A`

of the current state `x[t]`

combined with a transformation `B`

of the input `u[t]`

. Finally, the output `y[t]`

may be one of: pending todos, archived todos, or the next todo. These can be extracted from the state `x[t]`

with transformation `C`

.

## # How would this look like in `redux`

?

`redux`

is the incumbent leader in state management for frontend applications. Its documentation emphasizes *actions* and *reducers* and how it works under the hood. Let's focus on the transformations instead.

The transformation `B`

is most commonly performed with an *action* dispatch. Ie, the return value (except for `type: `ADD_TODO``

) of the following function is effectively `Bu[t]`

, the transformed input.

`function addTodo (payload) {`

return {

type: "ADD_TODO",

todo: parse(payload)

}

}

The transformation `A`

is then performed with a *reducer*, which combines the previous state and already transformed input to return the next state `Ax[t] + Bu[t]`

.

`function reducer (state = [], action) {`

switch (action.type) {

case "ADD_TODO":

return [ ...state, action.todo ]

default:

return state

}

}

Finally, the transformation `C`

is performed with one of many *selectors*, which returns the transformed state `Cx[t]`

. When used with `react-redux`

, this is what goes into `connect()`

higher order component, or the `useSelector()`

hook.

`function pendingTodo (state) {`

return state.filter(todo => !!todo.isPending)

}

function nextTodo (state) {

return state[0]

}

## # Common modelling errors

One very common modelling error is to omit the use of *selectors*, and the output `y[t]`

is exactly the value of the state `x[t]`

. Mathematically, `C = I`

, the identity function.

`x[t+1] = Ax[t] + Bu[t]`

y[t ] = x[t]

Not only does this unnecessarily grow the state, it grows the size of the transformation `A`

. Pending todos, archived todos, or the next todo are duplicated within the state, and can easily get out of sync.

Conversely, another common error is to store the input `u[t]`

(usually XHR responses) directly into the state `x[t]`

. Mathematically, `B = I`

, the identity function.

`x[t+1] = Ax[t] + u[t]`

y[t ] = Cx[t]

Doing so increase the complexity of the output transformation `C`

, and overly couples the input and output formats.

## # Much more than shifting transformations

Moving where the transformation happens increases semantic-ness. The bulk of state manipulation should live in `A`

; while `B`

and `C`

are used only to transform the input and output respectively.

The state `x[t]`

directly represents the domain model , and is not confused with input or output representations.

## # What about `mobx`

?

`mobx`

is another popular Javascript state management library. It heavily emphasizes reactivity by introducing concepts such as *observable* variables (proxies under the hood), *actions* to modify them, and *computed* attributes that are reactively updated.

Most `mobx`

practitioners are probably already implementing the state equations without realising it. In the example below, the `@action.bound`

annotated function applies the first line of the state transition equations. Then, the `@computed`

annotated functions apply the second line of the state transition equations.

`import { action, computed, observable } from "mobx"`

class Todo {

@observable todos = []

@action.bound addTodo (payload) {

this.todos.push(parse(payload))

}

@computed get pendingTodo () {

return this.todos.filter(todo => !!todo.isPending)

}

@computed get nextTodo () {

return this.todos[0]

}

}

The relationships are obvious, and very succinctly represented.

## # Not just frontend

Frontend applications is not the only place where these equations could be applied. Here's an example in Ruby on Rails. See if you can spot where the transformations `A`

, `B`

, and `C`

are.

`class TodosController < ApplicationController`

def add # mounted to a POST route

@todo = Todo.new(params.require(:todo))

@todo.save

redirect_to @todo

end

def pending # mounted to a GET route

@todos = Todo.pending

end

def next # mounted to a GET route

@todo = Todo.pending.first

end

end

class Todo < ApplicationRecord

scope :pending, -> { where(pending: true) }

end

## # Removing the state

It is illustrative to consider what happens when the state `x[t]`

is removed. Without state, the input `u[t]`

passes through 3 distinct transformations to become the output `y[t]`

.

`y[t] = CABu[t]`

As an aside, Control Theory calls these systems time-invariant . But again, we're not going that way in this article.

The first transformation `B`

changes the input format into a local format more suitable for processing. Then the second transformation `A`

processes the data. Finally, the third transformation `C`

changes it to the desired output format. Experienced database administrators may recognise this as the Extract-Transform-Load pattern.

## # Summary & Conclusion

All the above should be intuitively obvious. It is nonetheless comforting to know that behind this *software pattern*, is a whole field of engineering study.

Users of `redux`

, unfortunately often miss the opportunity to apply this pattern because of the strong emphasis on *actions* and *reducers*, without a corresponding emphasis on *selectors*. `mobx`

users, however more instinctly see the relationships from input, to state, to output transformations. Even *Ruby on Rails*, or other backend MVC framework developers are accustomed to the pattern, because MVC encourages this flow.

Finally, how the state `x[t]`

is stored greatly affects how complex the application will become. While it is tempting to use the same format as the input `u[t]`

, or the output `y[t]`

; it is usually far more meaningful to store it in the corresponding domain model.