A Rough Comparison of GUI Architectures
For the purposes of this book, the primary differences between the major GUI architectures is how data and control flow from the model data and the visual representation of that model data (the view).
The simplest, in many respects, is Model-View-Presenter:
![Model-View-Presenter](mvi-intro-2.png)
We have a UI, we have data, and we have glue code — in the form of a “presenter” — that ties the two together. The presenter is responsible for:
- Sinking events raised by the UI, such as form submissions, and using that information to update the stored representation of that data (the model), applying relevant business rules along the way
- Taking updates from the model — originating from this presenter, another presenter, asynchronous changes from a remote server, etc. — and updating its associated visual representation (the view)
It’s nice and straightforward. On Android, things get a bit interesting with configuration changes, so while early Android apps might consider the activity or fragment to be the presenter, nowadays they are considered to be part of the view (along with the widgets). The presenter is a separate object, one that can be (carefully) reused across configuration changes, as a stable platform as our activities and fragments come and go.
Ironically, what today is called Model-View-Presenter originated as Model-View-Controller. Long-time MVC fans — those who worked on Smalltalk development in 1993, for example — need to deal with this name change. Nowadays, MVC is a slightly different approach than MVP:
![Model-View-Controller](mvi-intro-1.png)
The principal difference is that now data changes from the model flow directly to the view, bypassing any intermediary. In Android terms, if the model is publishing RxJava streams, for example, the view is the subscriber of those streams, whereas in MVP, the presenter would be the subscriber.
The benefit of this approach is the unidirectional data flow. A presenter serves as a common junction for data flows, which is OK in simple scenarios, but can get messy in larger use cases. In particular, the presenter needs to keep track not only of the data, but who knows about that particular piece of data:
- Is this some interim POJO, updated from the view, that needs to get reflected in the model?
- Is this some interim POJO, updated from the model, that needs to get reflected in the view?
If you use the same POJO class for each — and particularly if you are applying caching to hold onto that data in the presenter — there is a risk of bugs causing the data to stop flowing. For example, you get a revised POJO from the model, you update the presenter’s cache… and fail to do anything to update the view. Or, you get data from the view, prepare changes for the model, then the model gives you new data from some other source, and you need to somehow merge this stuff together.
A unidirectional data flow, particularly with immutable objects, makes this simpler. Now, each component is responsible for doing some work and passing the results along to a single destination, rather than having to remember which destination needs the results of the work.
Microsoft led the charge to convert Model-View-Presenter into Model-View-ViewModel (MVVM). From a diagram standpoint, MVVM looks strangely familiar:
![Model-View-ViewModel](mvi-intro-3.png)
In fact, typically, a MVVM app still has something called a presenter, which is responsible for preparing the view-model and connecting it with the view. MVVM implementations tend to emphasize two-way data binding, so the “business logic” for updating the view-model lies in a declarative UI (e.g., Android’s layout resources, Microsoft’s XAML). For major operations, such as form submission, the presenter takes the view-model and uses that information to update the “real” model.
This helps to clean up the communications somewhat. The presenter is mapping from the model to the view-model, applying appropriate changes along the way, such as:
- Data minimization: only exposing data in the view-model that the view needs
- Data transformation: taking the data in the form that the model stores it and changing it to something more amenable to the UI, such as converting currencies, converting time formats (e.g., Unix epoch times to richer date objects), and so on
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.