In this article I will try to explain MVVM from my point of view as far as I can. In my opinion, to learn a piece of information, it is necessary to understand why we need it and how it meets our needs. That’s why at first I’m going to try to explain why we need architecture and design patterns.
Why do we need design patterns?
The software products are under constant change and development. Every change and development is shaped depending on the structure before it. This structure is the sum of the solutions to the problems we encounter.
The problems in software projects and their solutions are based on abstract concepts. That’s why finding solutions to problems becomes much harder. So we need rules to make abstract concepts more concrete. In fact the design patterns are grouped versions of these rules. The more solutions we implement according to these design patterns, the more understandable the code will be and the easier it will be to make future improvements.
Why layer-based design pattern?
First of all many design patterns can be used in an application. But here I will talk about the design pattern selection which forms the basis of the application.
I will try to explain why we need to use the layer-based design pattern through the general workflow. Take, for example, a banking application. Let’s assume that there is a request from the product manager: “Users should be able to apply for a loan from the mobile application”. Business analysts examine this request and determine business rules such as how much credit users can apply and what information users will be asked to fill in. UX/UI designers, on the other hand, determine how the information will be displayed and how the information will be received from the users following these business rules. From this point of view, we see two different sets of rules: one is business, the other is UI. If we divide the application according to these two main layers, we can both better understand the needs of other teams while developing the application, and we will code it more easily. Also when a change is requested, we find easily the parts which will be changed.
I mentioned above that the layers form the basis of an application. Now I will try to explain the equivalents of these layers in the MVVM design pattern. Before going into detail, I want to give you a small warning. The MVVM design pattern tells us on which layers we need to put the functions and how these layers should communicate with each other. It does not promise anything beyond that.
Business Logic — Model
Data types (UserName, Password, etc), access to data, business rules applied to these data are defined in this layer. For example, if you are logging into the application with a nickname, the nickname object itself and the rules to create it are defined in this layer. For the design decision of the classes defined here, DDD and Primitive Obsession topics can be examined.
- Domain Driven Design(DDD): In short, it is a design that suggests building business logic oriented classes. It aims avoiding technical terms and structures, so that classes will depend on the workflow terminology. In this way everyone who has domain knowledge can more easily understand the work done by the business logic in the project. Thus it helps strengthening the communication between the product experts and the development team.
- Primitive Obsession: It is an anti-pattern which can be described as the use of primitives instead of small objects for simple concepts. Let’s assume that we are storing password entered by the user. We usually store this information in the String type. But in fact the password has more properties than the String type. Assume that based on business rules the password must be at least 6 character long and must include one numeric character. These are verification rules that do not exist in the String type itself. In other words, a separate type must be defined in which the rules and properties of the password concept are defined.
UI Logic — View-ViewModel
ViewModel generally adapts the information coming from the Model layer to the View. That is where the display rules are modeled. The View directly communicates with the ViewModel. The ViewModel communicates with the Model layer. Actions from View are interpreted here. For example, let’s assume that we show a list of currencies on the screen. If a currency has risen, we need to code this rule in the ViewModel, if we want to show it green.
Application-based processes (OS-related processes, animations) are defined here. The View side must contain as less logic as possible. It should only adjust itself according to the signals it receives from the ViewModel. Using Data Binding will be very useful in keeping this layer as dummy as possible.
Communication Between Layers
We talked about the definitions of the layers. So how should these layers communicate with each other? The biggest difference that separates the MVVM from MVC and MVP is that the communication between layers is done using the observable pattern. In this way the Model does not know the ViewModel, and the ViewModel does not know the View. In other words, thanks to the observable pattern, we build a one-sided dependency. No layer is affected by the vast majority of changes in the next layer. In this way refactoring is much easier. Likewise, one layer can be used by more than one class on the next layer. For example, more than one ViewModel can depend on the same Model. As a result, if we can model these layers properly. We can make changes such as UI layouts with a very little touch.
While establishing the connection between these layers, we should not ignore the concept of “Loose Coupling”. For this, you can examine the LoD design guideline.
These layers are not the layers that indicate a certain class. Instead, these are abstract semantic layers. For example, let’s design a product detail screen. Although it might seem natural to create a class for each layer such as ProductDetailModel, ProductDetailViewModel, and ProductDetailView, it’s not necessary at all. Often we need to divide these layers into sublayers with different design patterns. Beside any class in any layer might depend on more than one class in the previous layer.
Let’s think of a screen consisting of 2 different fields where login credentials are entered and a currency list is displayed. The fact that these two fields are displayed in the same window does not mean that the data of these two fields should be kept in the same ViewModel. Displaying these two fields in the same window may make sense in terms of UX. But in terms of software, they are two views completely independent of each other. Therefore, in such a scenario, we need to divide the logic into 2 different structures: LoginView-LoginViewModel-LoginModel and CurrencyView-CurrencyViewModel-CurrencyModel. So, from a software perspective displaying them in the same window does not mean anything.
To sum up, these layers are completely abstract. When creating the classes that make up these layers, we must always keep in mind other software principles. The MVVM design pattern tells us on which layers we need to put the functions used in the application and how these layers should communicate with each other at a high level. It does not promise anything beyond that.