MVC is a great concept to create user interfaces in a sane way but it has its drawbacks. Let’s imagine a simple case: A login service.
What do we need? User name and password.
So the model looks like this:
String login; byte password;
Is that enough to create the view? Yes.
But where do we put the code to encode and check the password? Is that part of the model, the view or the controller?
It’s not really part of the model because the data model doesn’t care how we encode passwords. For the model, a password is just an byte array. That’s even enough to check passwords – to compare two byte arrays, you don’t need to know how they were created.
Is it part of the view? The view should just display a “*” per byte, it doesn’t do anything with passwords.
Which means the encoding method goes into the controller. This isn’t necessarily the right place – we’ve just run out of options.
Users can log into our service, now. But how do they register?
For registering, you should allow the user to repeat the password to avoid typos. The view is simple enough but where do we store the repeated password?
Do we really want to extend our data model for this case?
Also, we need a second password check which works with plain passwords. But the model only stores encrypted passwords. We could convert both passwords into one unencrypted string and store both into the data model for the typo check and encrypt them before saving the data in a database. And we could make the check work for both encrypted and unencrypted passwords and if we make a mistake, unprotected password end up in the database …
So this is where MVC fails: Editors often need additional code and data to edit the plain data model. I could put all this into the view but that would violate the separation of concerns: A view displays a model, it doesn’t contain one. Ideally, views and controllers should have no state at all.
This is what MVVM solves: Instead of using the “real” plain data model, each UI component has a “view model” which replaces the data model. This model contains all the information that the view needs and all special “business logic” where the business is “editing the data.”
The view model knows how to talk to the data model and we have again separated concerns. When the controller is started, it converts the data model into a view model. And when the controller saves the data, it tells the view model to update the data model.
This approach solves a whole host of problems:
- You can easily split complex data from the model into several, independent UI elements.
- You have a place where you can put business logic shared by view and controller
- Needs of the view and the controller don’t leak into your data model
- The data model doesn’t change while the editor is active.
The last point is important: With the MVC model, it’s hard to share the same model between threads and users because the controller could change parts of the model at any time. It’s often impossible to do these changes in an atomic way, so other controllers might see an invalid state.
With MVVM, you can create locks that protect the model as long as the view model updates the data model. The locks will only be necessary in these update methods and nowhere else. That means you will have a few distinct places where you will need locks and suddenly, the impossible becomes feasible.