Today we are going to talk about something which sounds confusing but truthfully isn’t; functional reactive programming (FRP) or just "reactive architecture" as it's also known when we talk about the overall approach to using it in an app.
In my experience engineers often think a reactive architecture is
But reactive architecture is none of these, it’s a simple design paradigm for enabling the data in an app to become more predictable and easier to scale.
They do have a point about state, but I think what they really mean is...
Firstly, the state lifecycle needs to be managed so that we know it will be set and read at the right times removing the unpredictability issue.
Secondly, we also need to make sure we can encapsulate the dangerous parts of our state and expose useful parts too removing the unpredictability issue even further!
Luckily we can solve this problem using functional reactive programming in our architecture, we can call this the reactive architecture!
Before looking at a reactive approach lets look at the problems in a normal event driven approach. Consider the following code which is designed to do a simple event update when our api data (usersData) changes…
In this code you can see how we are binding an event handler to our api and then triggering update functions when it changes (line 3). But when we do this, we are not properly encapsulating usersData because we can access it lower down the example (line 6). Because of this we run the risk of something reading or even changing this data after it is changed by the api. This leads us to the problem of unpredictability we saw in the last section. We want to avoid this.
So, consider the following;
In this code I have introduced an object called reactiveContext. The reactiveContext is a separate module which lets us funnel requests for updates and changes to our state through it. This reactiveContext does something called "boxing". This boxing allow us to put the state data into an encapsulated function (starting on line 4), then; it allows us to add listeners to it (line 3,8,13) which trigger when it updates.
By forcing access like this through a "context" we can intercept all updates to the base data userData using a callback function at each step. This gives us the ability to chain together functions which act on state that operate in a sequence.
We can also allow helper functions to be called on the data during it's movement through our context chain. These helper functions are usually implemented as prototype functions like .map() .flatMap() etc.
So, instead of dangerously responding to and directly reading state data across boundaries like in the first example, the reactiveContext lets us control the underlying data. Thus; we can control the lifecycle of updates and protect it when we need to. The major benefit to this approach is firstly the encapsulation becomes (functional) and secondly the lifecycle becomes (reactive), aka functional reactive!
We can visualise how a FRP/reactive architecture let's us clean up our data transformation that might happen in a chaotic event app; and then compare it with a more controlled manner afterwards;
At this point you are probably thinking - what about React.js? And that's a great question.
Because, guess why it's called React.js? It also uses the reactive approach! Each of the components in React create their own functional closure like we saw above. The React framework is simply the proxy itself and allows the passage of data through its render tree, but it does this using HTML bindings!
In our reactiveContext we were responding to changes of simple data. But in the React world our app responds to user interaction and changes to HTML data. But the idea is the same - a reactive interface which allows the encapsulation of data (state).
If you want to begin using a fully fledged reactive framework in your app and extend out the functionality in React, Angular or Vue (I highly recommend not overly relying on their implementation for complex parts of your app) then you should check out another reactive framework like Mobx.
Mobx is known as an observable framework that enables a functional reactive approach for using data and managing state in an app. It’s pretty easy to learn and we teach you how to use it in our course Ultra Fast Testing and TDD.
So we saw how using an FRP based reactive architecture lets us solve these problems because we can use functions and a centralised callback proxy to manage the state lifecycle and to improve data encapsulation. In reality we wouldn't use our own reactiveContext we would use a framework like Mobx or even RXJS.