MVC is dead – what comes next? – Part 2
The first part of this series gave an overview of the key concepts and listed some of the main advantages of using functional reactive programming techniques in UI development. Future articles we will focus on different components that are involved, starting today with the State component, a key ingredient of functional reactive UI programming.
Single Source of Truth
In MVC applications we usually differentiate between the domain model and UI state. For example if we implement the TodoMVC application (see screenshot below) following some kind of MVC-pattern, our model will probably only consist of a list of ToDo-entries, because they define our domain. But the model would not keep the current entry in the input field (“What need to be done?”). And it would probably also not contain the selected filter.
The State component of a functional reactive application on the other hand contains the complete state of the application. The domain model and the UI state are typically merged into a single data structure – a tree. The picture at the beginning of the article shows the difference between both approaches.
Why is this important?
If we have all state in a single place, i.e. a single source of truth, we can implement the View as a pure function.
This has many advantages: it is easier to understand, easier to reason about, and easier to test.
Immutability
The second important characteristic of the State is its immutability. We cannot change it.
If the state of the application changes, we have to create new data structures.
This may sound like a terrible waste. If we store the whole state in a tree and we have to create a new instance every time something changes, how can this be efficient? The trick is, that we do not have to copy the whole tree, but only a small part.
Imagine our applications state is stored in the tree shown above. We want to change the property of the green leaf node. The node itself has changed, therefore we need to create a new instance. We also need to create a new instance for the parent node, because one of its children has changed. But the other child of that parent has not changed and we can reuse it by referencing it from the new parent node. The same is true for all the other parent nodes up to the root node. We need to create a new instance for each parent on the path to the top, but we can reuse the other children. In the diagram we only have to create new instances for the blue nodes, which are only a small fraction of the tree in particular if the tree becomes huge.
Implementing State in Java
I have recently started an experiment to explore how the principles from functional reactive UI programming could be applied to Java and JavaFX. You can find the current state of the mini-framework ReduxFX and a sample application at GitHub.
Implementing the State component in Java is straight-forward. All elements of the state can be implemented as simple, immutable POJOs.
Unfortunately the standard-collections in the JDK are not really suitable for immutability. But luckily there are several alternatives out there, that you can use instead. My personal favorite at this point are the collections in Javaslang, which offer several additional benefits besides being immutable.
The code below shows the class AppModel from the sample project in ReduxFX. The property todos is of type Seq, which is part of Javaslang. Seq is similar to Iterable in the JDK, because it is the supertype of all sequential data structures in Javaslang (though Seq offers much more functionality). In other words todos is a list of TodoEntries.
The property newTodoText contains the text stored in the TextField for new todo-entries. Last but not least, the property filter stores the current filter (ALL, ACTIVE or COMPLETED).
package com.netopyr.reduxfx.todo.state; import javaslang.collection.Seq; import org.apache.commons.lang3.builder.ToStringBuilder; public final class AppModel { private final String newTodoText; private final Seq<TodoEntry> todos; private final Filter filter; public AppModel(String newTodoText, Seq<TodoEntry> todos, Filter filter) { this.newTodoText = newTodoText; this.todos = todos; this.filter = filter; } public String getNewTodoText() { return newTodoText; } public Seq<TodoEntry> getTodos() { return todos; } public Filter getFilter() { return filter; } @Override public String toString() { return new ToStringBuilder(this) .append("newTodoText", newTodoText) .append("todos", todos) .append("filter", filter) .toString(); } }
Summary
State in functional reactive UI programming is similar, but not the same as the Model in a classical MVC application. It contains all state, including UI state, and not only the domain model. In many frameworks the state is stored in a single data structure, usually in a tree. Another key requirement is immutability. Implementing the State component in Java is straightforward with immutable POJOs.
The next part will cover the View-function, which translates the State to the actual UI. If you have any questions, ideas or thoughts, please leave a comment. Also do not forget to checkout my JavaFX sample ReduxFX.
Reference: | MVC is dead – what comes next? – Part 2 from our JCG partner Michael Heinrichs at the Mike’s Blog blog. |