In last two or three years, we started to see the rise of Redux-based (or Unidirectional data flow architecture in general) in the user interface side of the applications, and the slowly decline of MVC based architecture in the UI side.
What Redux has of advantages over MVC, and what problems it solves? I am going to show what the benefits of Redux over MVC.
Redux library by itself is not enough to build a whole system, and this is why there is an echo system developed around Redux. I am going to show the basic echo system needed to build a Redux application, or the essential building blocks of a any redux-based application.
First, The Problem with MVC
To explain why Redux became so popular, let us see the problems with the existing MVC or MVC alike UI applications.
Let us see how MVC works?
The following diagram show the data flow and control flow for the strict MVC pattern.
There are other variations of MVC, specifically Model-View-ViewModel (MVVM) which was created specifically to represent the UI in a thick UI environment to help unit test the UI.
The following diagram shows the control flow in MVVM and MVP (Model-View-Presenter).
We can refer to all above patterns as MVW (Model-View-Whatever).
What the problem with MVW?
MVW is easy to manage in a simple application, with few models/controllers. But we can easily start to witness problems as we grow in size with the following problems:
- There is need when models/controllers communicate with each others (through a service layer probably), and these modules changes the states of each others, and the more controllers, the more easy to lose control of who changed the state of a controller.
- Asynchronous network calls to retrieve data add uncertainty of when the model will be changed or modified, and imagine the user changing the UI while a callback from asynchronous call comeback, then we will have “nondeterministic” status of the UI.
- Change state/model has another layer of complexity which is the mutation. When to consider the state or model is changed and how to build tools to help recognize the mutation.
- Adding to that if the application is a collaborative applications, (like google docs for examples) where lots of data changes happening in real-time.
- No way to do undo (travel back in time) easily without adding so much extra code.
We can summarize the above as : “There is no single source of truth of the applications at any given time.”, and at any give time we cannot know how the UI will be, and this create non-determinism UI.
“Nondeterminism = parallel processing + shared state” ~ Martin Odersky (Scala designer)
Redux is just one variation of a whole trend in UI architecture called :
Unidirectional User Interface Architecture .
For example there is Flux (Redux is just a variation of Flux), Cycle.js, MobX, and Elm has its own implementation of that architecture.
As stated from the Redux motivation, Redux tries to make: “state mutation predictable”, and it tries to achieve that by the following:
- Have one single source of truth (from the state)
- States are read only and immutable.
- Changes are made with pure functions.
We will explain all these points in details, when we see how Redux works.
How Redux works?
There is a wornderful diagram that describe the flow in Redux. I got this diagram from this presentation.
This is the data flow:
- Models/states in the application should reside in a container called “Store”. Even we can have many stores in an application, but Redux differs from others (like Flux) by leaning toward one store.
- Communication to the store should happen through one gate, which is a function called “dispatch”.
- The Store receives the actions, and pass it to “Reducers” which are pure functions that modify the store’s state and produce a new state.
- Store’s state is immutable, and any modification will generate always a new state.
- The Store will notify any subscribers about new changes.
- UI render itself, using pure functions taking the store’s state as input parameter.
- Asynchrounous network calls will modify the store through actions as everything else.
Why Redux is better ?
Redux solves many problems:
- Because we use pure functions everywhere, so alwas the output is deterministic, and we have deterministic UI.
- Logging actions, we can know who modify the state, and when exactly.
- Collaborative programs like (google docs) can be acheived easily by sending Actions on the wire and recreate them there.
- Easy debugging, by logging all actions on production we can re-create the whole situation.
- Deterministic UI, because UI rendering using pure function, and the same input will always generate the same output.
- Unit test is so easy, because we are testing pure functions for UI and state mutation.
Setup Redux application
I am going to speak here theoretically, and not writing any code.
To use Redux in an application, there are few libraries that you Must have and you cannot work without them (in my opinion):
- Redux itself:
First you need Redux itself, which is available through npm.
- integration with other libraries:
As we mentioned above, Redux’s store has one method called
dispatchand it has another method to subscribe to state changes called
subscribe. We can simply use these methods to communicate to the store. But most probably we are using another library for UI, and Redux community created an easy way to integrate with lots of libraries, for example angular has ng-redux, and React has react-redux. Even Backbone, and Elmer.
- middle-ware to handle asynchronous calls:
Preferably use middle-ware to handle asynchronous calls, so you will have a unified way to send actions regardless if you sending simple objects, or actions that do async calls. There are plenty of options, the simplest is redux-thunk. But more advanced will be redux-saga or redux-observable.
don’t do development without having a logger. It is a life-saving. redux-logger. It logs every actions with the state before and after the action.
- Immutable.js or Seamless-immutable:
There is more to the echo system
There is more to the echo system, but I only put the minimun that you must have to work. Although you don’t have to use them, and you can go away using Redux by itself, but expect some trouble when your application become more complex.