3

I've been using MVVM for a while now with WPF. And i've learnt a lot over the course of development (going from never using it, to having a couple of applications developed in it)

However, recently I had some comments directed at the code which made me wonder if i'm doing things the right way. My current setup works (roughly) like this:

  • Model - Responsible for storing the data, data validation using IDataErrorInfo and dirty tracking
  • ViewModel - Responsible for getting the data (from a repository like pattern) and formatting it for a view's consumption (things like filtering, ordering) also responsible for command handling from the view (save, load, filter changes etc)
  • View - The usual UI stuff

Now it was mentioned to me that i should NEVER have business logic inside the model, and that the model should be as thin as possible, the viewmodel should be responsible for handling things such as data validation and dirty tracking.

I've seen comments and criticism on both sides of this, with people against and for putting logic in the model, What i have yet to see is any actual reasons for these sweeping statements. So id love to know if there is an actual reason i should be refactoring my setup.

Also, given that i do move the logic to the viewmodel, I can see the need for having multiple viewmodels where i currently have a single, for example:

  • Person - Model
  • PersonViewModel - Handles the dirty tracking, data validation etc
  • PersonsViewModel - Handles getting a collection of PersonViewModels, filtering etc
  • PersonsView - The UI

This seems a little redundant, but perhaps i'm misunderstanding something. What I'm really looking for is some actual reasons for doing this one way or another, or if this is another argument like the use of code-behind in MVVM (pure opinion with little reasons etc)

Ben
  • 1,291
  • 2
  • 15
  • 36
  • you said that VM is resposible for getting the data. That may or may not be true. It depends on what best suits you, but MVVM design pattern does specify it. For example you may load all your data at application startup, before you create your first viewmodel. Or you may call you model, that includes dataaccess from viewmodel. – Liero Aug 12 '15 at 11:14
  • That's just my current setup, my viewmodels are responsible for talking to the Repositories which in turn talk with WCF services, but i have other app's that work differently. – Ben Aug 12 '15 at 11:38
  • "NEVER have business logic inside the model" - Never heard that before in relation to MVVM; will be interesting to read such article/discussion. – akjoshi Aug 12 '15 at 11:42
  • In typical internet fashion i cannot for the life of me find that article i read. I can find one saying to NEVER put it in the view model tho. Although the comments i mentioned receiving were not online. – Ben Aug 12 '15 at 11:47

4 Answers4

3

High level description of MVVM:

  • View: User Interface

  • Model: Business logic and data (e.g Domain Model+Repositories, or Transaction Script+POCO entities, etc)

  • ViewModel: Data exposted to view in such form, that is easily consumable from view. Wikipedia's definition says: The view model is an abstraction of the view that exposes public properties and commands.

I like the Practical MVVM Manifesto (archived version) principes: Simplicity, Blendability, Designability, Testability.

This is very high level and abstract description and that's why you may find a lot of variations of MVVM. Whatever mvvm style you choose, keep in mind the responsibilities and principles and you should be ok. Try to avoid complexity. MVVM is not a silverbullet and you cannot cover all scenarios with single design pattern. One mvvm implementation may be suitable for one application but not for another. I, for example, build my mvvm architecture from scratch for each new project to ensure the best fit


When is comes to responsibilities:

Take validation as an example: validation logic that password and repeat password inputs should be equal is clearly presentation logic and should be present in viewmodel. On the other side, there may be business rule, that password must contain at least one special character. This logic should reside in Model, however you may expose it in viewmodel to be easily consumable from view. It's a business logic, but you may need to present it somehow.

if you have application that only uses webservice to retrieve and store then your model will be probably just the data access components.


Here is couple of resources:

Wikipedia: https://en.wikipedia.org/wiki/Model_View_ViewModel.

MVVM is variation of Martin Fowler's MVP pattern, you may find it useful as well: http://martinfowler.com/eaaDev/PresentationModel.html

MSDN (Pattern and practices): https://msdn.microsoft.com/en-us/library/hh848246.aspx

Shoter
  • 976
  • 11
  • 23
Liero
  • 25,216
  • 29
  • 151
  • 297
  • Thanks, that is a well rounded answer, in your opinion would IsDirty tracking be a viewmodel or a model's responsibility? currently i have it on the model, but I was told that is a viewmodels responsibility. – Ben Aug 12 '15 at 11:28
  • 1
    @user1412240 Okay. Why do you need to know about dirtyness? In general, I find that a good way to divide the logic is re-usage and testing. The model is business logic that should be usable even when you write a MVC website. The divide between VM and V is that the VM is unit testable. – Aron Aug 12 '15 at 11:39
  • Well, thinking about it after seeing all this, I guess it would be VM role, as i use IsDirty to enable save buttons, prevent navigation without saving (or at least notify the user). All very much a interface level logic – Ben Aug 12 '15 at 11:40
  • Well, it depends. If your PersonViewModel just exposes Person model which already has changetracking and you bind directly to Person, than it's ok. In other scenario, you may want to update Person's properties only when save button is clicked. If you want to enable save button only if something has changes, you need to implement change tracking in viewmodel. I recommend to start with simplest approach that does not break the high level mvvm principles but be prepared for change. – Liero Aug 12 '15 at 11:50
  • 1
    Sorry for the late reply on this, i didn't get a notification of this comment. I'm always prepared for change that's what lead me to this question haha, I think i prefer the change tracking on the VM, as change tracking wouldn't be used outside of the WPF MVVM application so doesn't belong on the model – Ben Aug 13 '15 at 08:04
2

I like to think of the Model layer as anything that has nothing to do with how the app is hosted (i.e. independent of WPF). It is one or more dlls that represent the business domain and the operations that need to be performed in it. If it would make sense to take theses same dlls and use them in a web application, windows service e.t.c then it is usually a sign that the split between Model and ViewModel is appropriate.

Matt Cole
  • 2,491
  • 17
  • 21
  • Right, so if I'm understanding you correctly. Your reason is re-usability, Ability to use the same model classes across the service layers as well. Ok that's a good reason i can get behind, thankyou – Ben Aug 12 '15 at 09:53
  • Conceptually yes. After all the "Model" in MVVM is the same model that is in MVC and many other design patterns. You might be interested in the opinions [here](http://stackoverflow.com/a/4415941/4832982) - a similar question about MVC. – Matt Cole Aug 12 '15 at 10:30
  • Intresting, thats the opposite of the comments I received about keeping logic out of the model, but again the answer makes perfect sense to me. It would appear all this comes down to is personal preference and the needs of the application. I guess my point of confusion was the need for additional viewmodel that have no view (I've always understood that a viewmodel is FOR a view only) – Ben Aug 12 '15 at 10:33
  • I totally agree with this, as much as possible business logic should go in Model, just wanted to post exact same reasoning. – akjoshi Aug 12 '15 at 11:39
  • "keeping logic out of the model" - maybe they were talking about keeping logic out of entities - about anemic entities. That means that entities does not have any behavior. In some simple scenarious the behaviour may be purely in viewmodels, but more complex scenarios require reusabe behaviour and you need to create some kind of business classes that represents the behavior - e.g transaction script. Notice, that entities in not the same as model. In this case, model is both, anemic entities and transaction script. – Liero Aug 12 '15 at 12:17
1

There's no simple answer to your question. The simplest answer is that the model and view model should contain the code that you should unit test. The separation between model and view model is a little less distinct. I like to keep the model as simple as possible and limit it to whatever is exchanged with the server tier. The view model should encapsulate the model, and provide any addition functionality (both business logic and abstract presentation logic) so that you can keep the presentation layer as simple as possible (declarative, in the case of WPF XAML).

Paul-Mason
  • 41
  • 1
  • Is the fact you like keeping the model thin simply a personal choice? Also does that mean my assumption about multiple viewmodel's is the way you would choose to do things? – Ben Aug 12 '15 at 09:45
  • It's a mixture of personal choice and research on the topic. Yes, I often have multiple view models for a single model - the view models are view specific, while the model is more generic. – Paul-Mason Aug 12 '15 at 09:48
  • Just a quick clearup, would you say my example (Person, PersonVM, PeopleVM) is the way you would do it? given that at this moment there is no personview? – Ben Aug 12 '15 at 10:00
  • 1
    Without knowing exactly what data the various models contain, I would say yes. Although, it may be enough for the PeopleVM to contain a list of Person models, if the only purpose of the people view is display data that is contained in Person. – Paul-Mason Aug 12 '15 at 10:15
  • Yeah, I can go with that, the idea would be what i wanted to edit in that view, say directly from a gridview and you pretty much answered that. Thanks. – Ben Aug 12 '15 at 10:16
1

I see it this way:

Model - Object that can be passed around. A Common type between different layers for communication.

ViewModel - Specifically created for Views. This should contain UI logic, for example, Data Annotations etc will go here. You might also call your web service methods here (assuming your actual business logic sits in a facade layer, or your database logic sits in a different layer/project) to populate the Views, dropdowns etc. You might end up with multiples of these per view, depending on your design.

View - UI Only.

I am not afraid to put external calls in the ViewModel

  • Ok, that all make's sence and seems the be the main school of thought, But what about the point of having a viewmodel with no corresponding view? – Ben Aug 12 '15 at 10:15
  • A ViewModel might point to a controller of some sort. That controller is part of the main view –  Aug 12 '15 at 10:16