I regularly see a lot of questions around MVVM, last one only a few weeks ago.
The problem is usually the same: what should be a Model, and what should be a ViewModel?
We can’t really blame developers, because references online are not really good, especially MSDN’s one. The explanation is simplified to be understandable for most developers. The result is an oversimplified pattern which doesn’t fit for complex line of business application.
There are many contradictory implementations of MVVM. I’ll describe in this post an effective implementation for me since many years.
Everybody agree on a ViewModel definition: it is an abstraction of a View. This abstraction is simpler to test than the GUI, we don’t need to run the solution to test a ViewModel in isolation. It decouples UI design from UI behavior.
But what should be in this ViewModel abstraction is really unclear. Usually the implementation is a ViewModel where we put too much business logic, and a simple POCOs Models (mainly because of ORMs). In this case, a question arises: when I use only one Model in one ViewModel, do I need a ViewModel at all ? Can’t I just bind the model and notify the View if one of the properties is updated ?
Domain Model is a tactical pattern from Domain Driven Design (DDD), which could fit the Model in MVVM. Using DDD, we want to avoid Anemic Domain Model, which clarifies what could be a MVVM implementation.
The ViewModel is only an abstraction of the View, and it manipulates Models where the business logic is.
For example a ViewModel can use a User to change an address:
user.ChangeAdress(new Adress(“3 route de tartampion”, “6900”, “Lyon”, “France”));
[/cc]What if I need several Models?
Another tactical pattern from DDD could help us: Domain Service. A Domain Service is where we manage interaction between Domain Models. We use it if we do not find a better place to put the business logic for a given use case. Our ViewModel will manipulate Domain Services, which manipulate Domain Models. Typical use case requiring several Models is validation.
For example a ViewModel can use a buying service to validate a command:
_buyingService.Validate(/*products to buy*/, /*current user*/)
What if I don’t know/care about DDD?
Just replace the word DomainModel by Model, and DomainService by BusinessService. Apply SRP to well design classes.
For example in C#, a Model should not be INotifyPropertyChanged, it is a UI concern. It’s the responsibility of a ViewModel to notify a View when a property changed.
- A View has the responsibility to display something to our user. We don’t want any behavior here.
- A ViewModel has the responsibility to represent the behavior of our View. We talk about UI behavior, not Business behavior.
- A Model has the responsibility to encapsulate the business logic, and do not care about how it will be display. It’s where we put business behavior.
- A Business Service has the responsibility to encapsulate the business logic for a given use case, if several Models are involved to meet a business needs.
I tried to give a simple example on Github. (Note that I let the DDD part away).
Any feedback welcome.
Thank you Brian Gibson for the suggestion to add diagrams.