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.
Problem roots
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:
[cc lang=”csharp”]
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:
[cc lang=”csharp”]
_buyingService.Validate(/*products to buy*/, /*current user*/)
[/cc]
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.
In the same idea, a ViewModel should not embed business logic, since it is already responsible for UI behavior. Simple rules for simple design
- 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.
Hi Ouarzy,
Interesting article, happy to see that I’m not the only one to think about good correlation between ddd and mvvm.
However, I think it is dangerous to expose domain models to viewmodels. The more you expose your domain models to external world the more you create coupling.
I prefer to communicate from viewmodels to bounded contexts through ddd application services or cqrs command/query dispatcher. This keeps
front-end models decoupled from domain models.
Furthermore, if you decide later to host your Domain in a microservice, it helps the transition because you already manipulate endpoint to bounded context and not domain models directly.
This is probably what you mean with usecase services, but it didn’t make sense to me 🙁
Hi Pierre! Thanks for sharing.
Of course I fully agree, the goal is to help a no DDD practicioner (like in the SO question) to see what they could do easily to keep a clear separation of concern.
What I mean by usecase services is closer of a DomainService in DDD, but of course what I describe here is not a full MVVM/DDD implementation.
It is just a MVVM implementation with a clear separation of concern, mainly because I don’t understand why people believe it’s a good idea to have a Model which directly notifies a View.
Hi Ouarzy,
Thanks your sharing.I have a question. Some time we change the model property and need to notify two views to update it. If we don’t have the model directly notifies , we may do much work to achieve this requirement. Is there any better implementation?
Hi Karl, thanks for the question.
In this case, instead of one model for two views, you may have one viewModel (or at least the common part) for two views, that’s all.
If you prefer, your viewModel abstract a view, thus if two views seems to share a lot of common data, they may share a part of a viewModel.
Now to be fair, even if it seems ok in theory, I never saw a “sharing same viewModel for different view” strategy to be successful on actual projects. It usually creates less readable code.
Hope it helps.
Hi Ouarzy,
Thanks for your article. You mentioned that, “a Model should not be INotifyPropertyChanged, it is a UI concern.” In that case, what’s the best way to inform the ViewModel that things have changed in the model? You can imagine that for complex logic, a call to a domain service may have changed several models, perhaps added items to collections in a model or changed several properties. How does the ViewModel know what needs to be updated?
Thanks.
Dear Carlos, Thanks for reading.
Did you look at the example code on Github? I think I don’t fully understand the question, but normally a given VM know what needs to be updated because it manages the business transaction. If another VM needs to load Models that have been changed somewhere else, it is not a problem because I pull fresh data when I open this new VM.
Hope it helps.
Thanks for your answer. Yes, I looked at the example, but my main view is more complex and contains several subviews (each with its own VM) in tabs. If I call a command on one VM, it calls a domain service, which makes several changes to the model. Now some of my sub-VMs need to be refreshed with the new model data. I don’t want to specify which VMs to refresh in the command because I think that’s domain logic leaking into the VM. I could refresh the entire VM (including all sub-VMs it contains), but then the response time of the UI goes down. Perhaps the solution is to simplify my complex view and break it down into pages rather than tabs. If you have any suggestions for handling this, I’d appreciate your thoughts.
Thanks for your help!
Well, my first advice would be: easier is better 🙂
Now for your scenario I will usually use an EventBus. The command in one of the subVm will raise an event (like PersonAdressChanged).
Other SubVm displaying person adress information will subscribe to this Event and update themsleves accordingly.
It allows good response time and keep clear responsability, each VM only know which events it should handle.
That’s my thoughts 🙂
Thank you!
Thanks for the write-up.
I’ve seen many people recommending implementing INotifyPropertyChanged and IErrorDataInfo on models (even in Pluralsight courses, see “Design Patterns Library” course, the module on MVVM, surprisingly by Brian Lagunas, Prism framework maintainer). Which seemed wrong to me. Like you said, these interfaces are for view-models, not for models.
Do you plan to write (a few) more articles on MVVM?
Hi Andrew.
Thanks for your feedback.
You’re right, most of the courses and online references (including from Microsoft) are recommending implementing INotifyPropertyChanged on the model. Of course the problem is that I don’t know how different it is of a VM in that case, in terms of responsibility.
When you are working since a long time with this architecture, you see quite easily that the code become harder to maintain, because the business logic is everywhere, and everybody can update the UI.
But in the short term (or for little project), model implementing INotifyPropertyChanged may seem easier and/or faster. Which is why, I believe, most “How To” guide use this approach.
What kind of article on MVVM would you like to see?
As I said, all these concepts comes from the Domain Driven Design world, and I write a lot aout DDD 😉
Here is a situation . On the View there is a button which is connected with a command ,the fuction of the command is to add a student . Besides the button ,there is a ListView , a detail form , now I fill in the form and trigger the button and the command execute ,finally a new student is add to domain . The question is how I can update the ListView in order to add the new student on it. sorry for my poor Englsih. Thank you !
You want to bind the List of students to the data source of the object in your view displaying the students list.
Also you generally want to use an ObservableCollection instead of a list, to trigger the INotifyPropertyhanged in order to update the view 🙂