A good application is like a good gift, it can surprise you. And the most surprising in good applications is always the state. That’s why Redux became so popular in web development. But what’s wrong with traditional approaches?

Massive [put your class name here].

You’ve probably seen many classes in your life that have too much responsibility. MVC jokingly stands for Massive View Controller, because single view controller is usually responsible for catching user interaction, invoking network requests, parsing data, etc. The case looks similar for view models in MVVM architecture or presenters in MVP pattern. They all do too much. Beside the fact, that it’s a bad programming practice, primarily it complicates your app state management. Unexpected errors, weird collection elements, looped callbacks — it’s just a matter of bad state. What you’re about to see is an attempt of solving this problem.

One state object to rule them all

The core of the solution, I am trying to present, is to store the entire application state in one object. You’ll see that it’s not as crazy as it seems at first glance. What’s more, there is only one group of objects that can modify this state — they’re called mappers. Mapper is a function that takes current state and input (you can treat it as an action) and returns a new state. All of this is packed into an algorithm called automaton. But how does it work exactly?

Whenever we’ll try to change the state of our application, we need to send an Input to the Automaton , which is a singleton object. It uses instance of Mapper (has to be implemented by us), not only to refresh the state upon old state and accepted input, but also to emit an optional output. As shown on the diagram above, output can become a new input and repeat whole operation.

Let’s see an example

Imagine creating an application that displays a list of contacts. What we need to store in our state?

isLoading — whether we are loading data from the database.

— whether we are loading data from the database. contacts — current collection of displayed contacts.

The initial values for these objects would be false and an empty collection. When view becomes visible, we would like to start process of loading. In order to do that, we can send LoadContactsInput instance to the automaton. Then, the mapper should capture this input and change isLoading value to true. It’s not everything yet, because we can also emit the output. In this case, it would be an asynchronous task that gets contacts from the database and then it transforms into SetContactsInput with the appropriate collection inside. After that, the mapper should capture new input too and update the value of contacts .

With great power comes great responsibility

Adding new features is always related to possibility of new errors. By formalizing all the changes taking place, we not only reduce the risk of error occurrence, but also we make it easier to understand the application design. Using mentioned approach will help us to build a reactive program that controls internal data flow. In the following articles I will describe how exactly the implementation of the automaton works and I will show real examples of Model View Automaton pattern. What’s the best about this idea is that we don’t have to create applications from scratch, but we can add it to already existing projects.