Why Use Mvvm

Why use MVVM?

Summary

  • The usage of all patterns is situational, and the benefit (if there is any) always lies in reduced complexity.
  • MVVM guides us how to distribute responsibilities between classes in a GUI application.
  • ViewModel projects the data from the Model into a format that fits the View.
  • For trivial projects MVVM is unnecessary. Using only the View is sufficient.
  • For simple projects, the ViewModel/Model split may be unnecessary, and just using a Model and a View is good enough.
  • Model and ViewModel do not need to exist from the start and can be introduced when they are needed.

When to use patterns and when to avoid them

For a sufficiently simple application every design pattern is overkill. Assume you write a GUI application that displays a single button which when pressed shows "Hello world". In this case, design patterns like MVC, MVP, MVVM all add a lot of complexity, while not adding any value whatsoever.

In general, it is always a bad decision to introduce a design pattern just because it somewhat fits. Design patterns should be used to reduce complexity, either by directly reducing overall complexity, or by replacing unfamiliar complexity with familiar complexity. If the design pattern cannot reduce complexity in either of these 2 ways, do not use it.

To explain familiar and unfamiliar complexity, take the following 2 sequences of characters:

  • "D.€|Ré%dfà?c"
  • "CorrectHorseBatteryStaple"

While the second character sequence is twice the length of the first sequence, it's easier to read, faster to write, and easier to remember than the first sequence, all because it's more familiar. The same holds true for familiar patterns in code.

This problem gains another dimension when you consider that familiarity depends on the reader. Some readers will find "3.14159265358979323846264338327950" easier to remember than either of the above passwords. Some won't. So if you want to use a flavor of MVVM, try to use one that mirrors its most common form in the specific language and framework you're using.

MVVM

That said, let's dive into the topic of MVVM by means of an example. MVVM guides us how to distribute responsibilities between classes in a GUI application (or between layers - more about this later), with the goal of having a small number of classes, while keeping the number of responsibilities per class small and well defined.

'Proper' MVVM assumes at least a moderately complex application, which deals with data it gets from "somewhere". It may get the data from a database, a file, a web service, or from a myriad of other sources.

Example

In our example, we have 2 classes View and Model, but no ViewModel. The Model wraps a csv-file which it reads on startup and saves when the application shuts down, with all changes the user made to the data. The View is a Window class that displays the data from the Model in a table and lets the user edit the data. The csv content might look somewhat like this:

ID, Name, Price
1, Stick, 5$
2, Big Box, 10$
3, Wheel, 20$
4, Bottle, 3$

New Requirements: Show price in Euro

Now we are asked to make a change to our application. The data consists of a 2-dimensional grid which already has a "price" column, containing a price in USD. We need to add a new column which shows prices in Euro in addition to those in USD, based on a predefined exchange rate. The format of the csv-file must not change because other applications work with the same file, and these other applications are not under our control.

A possible solution is to simply add the new column to the Model class. This isn't the best solution, because the Model saves all the data it exposes to the csv - and we do not want a new Euro price column in the csv. So the change to the Model would be non-trivial, and it would also be harder to describe what the Model class does, which is a code smell.

We could also make the change in the View, but our current application uses data binding to display the data directly as provided by our Model class. Because our GUI framework doesn't allow us to introduce an additional calculated column in a table when the table is data bound to a data source, we would need to make a significant change to the View to make this work, making the View a lot more complex.

Introducing the ViewModel

There is no ViewModel in the application because until now the Model presents the data in exactly the way the Csv needs it, which is also the way the View needed it. Having a ViewModel between would have been added complexity without purpose. But now that the Model no longer presents the data in the way the View needs it, we write a ViewModel. The ViewModel projects the data of the Model in such a way that the View can be simple. Previously the View class subscribed to the Model class. Now the new ViewModel class subscribes to the Model class, and exposes the Model's data to the View - with an extra column displaying the price in Euros. The View no longer knows the Model, it now only knows the ViewModel, which from the point of the View looks the same as the Model did before - except that the exposed data contains a new read only column.

New requirements: different way to format the data

The next customer request is that we should not display the data as rows in a table, but instead display the information of each item (a.k.a. row) as a card/box, and display 20 boxes on the screen in a 4x5 grid, showing 20 boxes at a time. Because we kept the logic of the View simple, we simply replace the View entirely with a new class that does as the customer desires. Of course there is another customer who preferred the old View, so we now need to support both. Because all of the common business logic already happens to be in the ViewModel that is not much of an issue. So we can solve this by renaming the View class into TableView, and writing a new CardView class that shows the data in a card format. We will also have to write some glue code, which might be a oneliner in the startup function.

New requirements: dynamic exchange rate

The next customer request is that we pull the exchange rate from the internet, rather than using a predefined exchange rate. This is the point where we revisit my earlier statement about "layers". We don't change our Model class to provide an exchange rate. Instead we write (or find) a completely independent additional class that provides the exchange rate. That new class becomes part of the model layer, and our ViewModel consolidates the information of the csv-Model and the exchange-rate-Model, which it then presents to the View. For this change the old Model class and the View class do not even have to be touched. Well, we do need to rename the Model class to CsvModel and we call the new class ExchangeRateModel.

If we hadn't introduced the ViewModel when we did but had instead waited until now to do so, the amount of work to introduce the ViewModel now would be higher because we need to remove significant amounts of functionality from both of the View and the Model and move the functionality into the ViewModel.

Afterword on Unit Tests

The primary purpose of MVVM is not that the code in the Model and the ViewModel can be put under Unit Test. The primary purpose of MVVM is that the code is broken up into classes with a small number of well defined responsibilities. One of several benefits of having code consisting of classes with a small number of well defined responsibilities is that it is easier to put the code under Unit Test. A much larger benefit is that the code is easier to understand, maintain, and modify.

Why to use MVVM instead of MVC in android

MVC(Model View Controller)

I think this is the most widely used approach in Software Development. Model View Controller consist of three main components, around which the whole architecture is revolving.

View:- This component directly interacts with user and is responsible for how user going to see our application. In MVC, Xml is treated as view.

Model:- Model is the data Source for the Application and the main business logic is defined here, it contains data objects that are used in application and is shown to user. Data Source can be Web, local database(sqlite) etc.

Controller:- Here comes the important part of MVC pattern, Controller is the component that manipulates, edit, uses data model and show it to users via View. Controller is responsible for gathering all data and act as middle men between model and view. Activity/Fragments are considered to be Controllers in Android.
Sample Image

MVVM (Model View View-Model)

Model View View-Model is introduced in last year’s Google I/O.This architectural plan is becoming popular by the features it provides. It mainly implements the Data Binding Framework, it allows for “binding” of views to fields on an arbitrary object. When a field is updated, the framework is notified and the view is updated automatically. The architecture introduces two-way communication between its components. Along with features like binding, Automatically updating views, it also easy for testing purpose.The functionality of Model and View is same as we have discussed in MVP.

View-Model :- It is responsible for exposing methods, commands, and other properties that helps to maintain the state of the view, manipulate the model as the result of actions on the view, and trigger events in the view itself.View has a reference to View-Model but View-Model has no information about the View.There is many-to-one relationship between View and View-Model means many View can be mapped to one View-Model. It is completely independent of Views.

MVVM is the best architecture for android app development. You can understand more about it by table give below.

Sample Image

Why should i use MVVM?

MVVM eases automated testing, and it helps you keep your code clean through a separation of concerns.

If you don't do automated testing, mainly the second reason remains (there are other, minor advantages, but this is the main one IMO). If you're having a hard time with pure MVVM, you might want to consider using a hybrid approach: Keep as much as possible in the view model, but don't be afraid to use code behind if it makes your code more readable.

Don't forget: MVVM is a tool, not a goal! It's supposed to make your life easier, not harder. If you have to write 50 lines of boilerplate code over two layers of indirection just to avoid a single-line GotFocus handler, you might be overdoing it.

When NOT to use MVVM?

I can think of two circumstances under which I wouldn't use MVVM.

One is if the application's simple enough that I don't need a separation between the view model and the model. Does it muck up my class too much if I implement INotifyPropertyChanged and a RelayCommand or two? If not, I might skip the step of creating a separate class. Or I may just want a view model to mock up a functional UI, and worry about implementing actual back-end functionality if the client bites.

The other is when I need high enough performance, and there are enough objects in the view, that I need to write code that manipulates WPF objects directly. I haven't actually benchmarked it to be sure, but I'm be reasonably certain that drawing 1000 moving particles by iterating through an array containing them and modifying their TranslateTransform directly (if indeed that's the fastest way to position them) is going to be faster than modifying their base properties and having binding do it.

Why MVVM and what are it's core benefits?

I'll point you to a particularly useful video by Jason Dolinger.

Coming from a WinForms world, implementing any MVX style pattern seemed like more hassle than it was worth but after working with WPF for a couple of years now, I can honestly say that I wouldn't consider anything less. The whole paradigm is supported out-of-the-box.

First off, the key benefit is enabling true separation between the view and model. What that means in real terms is that if/when your model needs to change, it can without the view needing to and vice-versa.

Secondly, while your model may contain all the data you might need in your view, you may want to abstract that data in such a way that your model doesn't support. For example, say your model contains a date property. In the model it can exist solely as a DateTime object but your view might want to present it in a completely different way. Without the viewmodel you'd either have to duplicate the property in the model to support the view or modify the property which could seriously obfuscate the 'model'.

You can also use a viewmodel to aggregate parts of your model that exist in separate classes/libraries to facilitate a more fluent interface for the view to deal with. It's very unlikely that you'll want to work with data in your code in the same way that a user will want to or will want that data presented to them.

On top of that, you get support for automatic two-way data binding between the view and viewmodel.

There really is a whole bunch of extra stuff that I could bang on about but Jason say's it far better that I could so my advice is watch the video. After a few days of working like this, you'll wonder how you ever got by without it.

Good luck.

Why use a View Model (MVVM) in iOS?

My bad experience with the extensions approach was the basis for the first and most important part of my March 2016 talk at iOSoHo in New York. Most of what I said about extensions is not in the slides. There are several issues with the extension approach:

  1. You can only ever have one mapping of a model to a view (without another intermediate layer to provide that logic coordinating extension properties). This greatly impairs view reusability.
  2. Regarding point 1, even if you do coordinate around this, you're likely to get collisions if you're using the model many places, for example a name and then later adding firstNameOnly, etc. Definitely a model can only ever conform to a protocol one way, if you're tempted to go that way.
  3. Providing dummy values in lieu of the model, for doing auto layout, debugging, error cases, etc., is almost impossible. You'll probably find yourself writing a struct for that--that's a ViewModel.
  4. If you have a view that needs multiple models to populate it, or needs info outside the model, a view model simplifies their coordination.

With a ViewModel these important cases become trivial. (In the talk I call "commands" because they perfectly match the Gang of Four Design Patterns definition of command; Design Patterns notes also known as Action, i.e. UIAlertAction.)

I take the approach that a "ViewModel" should be lightweight, immutable, and distributed through unidirectional data flow. They have stored properties but but this is just to move data around, the VMs themselves are immutable and disposable. This is similar to the approach mentioned by Facebook at iOSoHo March 2017, though I think they don't call them View Models, just lightweight objects. You could put more complex logic in there but really best to, at most, call out to more complex logic handled elsewhere.

One addition I think is key, my rule is that a "ViewModel", whatever you call it, should have no properties that can't be written by a programmer looking at wireframes. So a var dateString : String not var date : NSDate. This is my cheeky term in the slides, "Modal Object Attribute Transformer". But it's mnemonic for a serious point: A castle needs to be able to raise the drawbridge and carry on when under siege; a view needs to be fully functional when the network is cut off (or doesn't yet exist). You will have much easier time in so many scenarios than if your view can do that.

Just a few weeks ago I took this approach and was able to create multiple complex screens in about 4 days, working only from designs, that will eventually be populated by data from the network but currently without any model or networking layer whatsoever. When the data layer is ready, I can simply write some creational methods init(with: Model) or better static func withModelforCase1(_ model: Model) -> ViewModel and write the mapping in the creation method, then when the model is connected, replace static func debugCase1() -> ViewModel with these creation methods. As the model evolves the compiler will throw errors here and only here; as the view evolves, adjust the ViewModel, and again the compiler will throw errors here and only here. No other code would need to be touched.

Extensions seem very elegant at the start, but actually create a tight coupling between models and views. Some kind of ViewModel approach is a robust system the needs of modern iOS apps--and modern iOS app development.

Benefits of MVVM over MVC

Its a very slim distinction, which I can explain best by comparing MVC in ASP.NET and MVVM in WPF.

In ASP.NET MVC the request comes in from the web server and is handled directly by the Controller. The Controller determines the appropriate View and populates it with Models. The Controller then releases these instances to the underlying system which renders a result to the client. You can see that the Controller is first and last to act.

In MVVM, the UI (the View), faces the user and takes user input directly. Within the View, Commands within the ViewModel (which is the DataContext of the View) are triggered by this activity. Control flows to the ViewModel which interprets what the View has sent it and prepares its Models. After control flows back to the View it updates itself according to changes in the Models. If a new View is required, the ViewModel communicates this with the NavigationService (or whatever method of navigation your application uses), which is the purview of the Window or Frame--UI components. You can see that the ViewModel isn't first and last to act; the View plays a much greater role than in MVC.

The architecture of WPF/Silverlight is the reason why things are done this way. The command, binding and navigation infrastructures can't be controlled/replaced by the Controller; they are tightly integrated with the UI. So the Controller must sit below the View and take a more passive role.



Related Topics



Leave a reply



Submit