14

When I'm processing business logic in an MVVM app. Should I do this on the Model or the ViewModel?

For example, if I want to re-calculate costs after an Asset has been re-valued, should I operate on the Model?

Is there an advantage in doing this on the ViewModel instead?

What happens if I have a list of ViewModels, but I want to translate that into a list of Models so I can do some processing? I could expose the Model as a property of the ViewModel (and use that to build the list of Models). But that means that the View will be able to access properties of the original Model

Mitkins
  • 4,031
  • 3
  • 40
  • 77
  • 1
    Add it in the model, viewmodel is mostly on presentation only and intermediary between the presentation and the model (data carrier). Another use of viewmodel is not to touch the structure of the model if you want to add fields that should not be reflected in the database add it in the viewmodel. In this case model is untouched – Anonymous Duck Jun 07 '16 at 06:22
  • 2
    Wrong community, this is better located at [Programmers](http://programmers.stackexchange.com/). – Toxantron Jun 07 '16 at 06:34

4 Answers4

28

My suggestion is to put logic in a service layer instead. This is a middle layer between view model and model (which, in a real object oriented paradigm, should only contains properties). So the correct life circle may be: View model -> service -> model handling. This allows also to reuse business logic code through others view model if needed

Fabrizio Stellato
  • 1,727
  • 21
  • 52
  • 1
    This makes sense. So in this case, how is the view bound to properties on the model? If the view is bound to the model, not the view model, then the view model seems kinda redundant. If the view is bound to the view model, then how are 2-way bindings implemented, so that model changes effected by the service are propagated back to the view? – David Kirkland May 09 '17 at 13:59
  • view bounds viewmodel. viewmodel is often: - class bounded by view that contains data bounded by ViewModel and call the service layer - a wrapper of the model used by view or by another viewmodel used as written above - service call the "pure" model - service return some data that is served by viewmodel that is bound by view – Fabrizio Stellato May 10 '17 at 08:27
  • This sounds like a good idea, but how do you actually implement it? For example I have a method called `UpdateTiming()`, it calculates three properties. Initially when refactoring I passed in my ViewModel as an argument so that it could set those values and the UI would update. But now the service is tightly coupled to the ViewModel. Instead should I pass the model as an argument and return a tuple then update the properties from in the ViewModel? Seems like a lot of extra code. – Adam Jul 21 '17 at 19:52
  • @Adam I hope you've figured it. Services generally work on the model and either return model(s) or whatever is appropriate in the case. The value returned by the service is used to `new` up a ViewModel object. Makes sense? So in most cases you'll want to convert a Model to a ViewModel and sometimes vice-versa and you can use a mapper like [this one](http://automapper.org/) for that. – galdin Oct 29 '17 at 06:51
  • 1
    +1 This should be the accepted answer. Complex business logic should be written into a service layer and be used by both ViewModel and Model. – zwcloud Jun 17 '20 at 03:45
  • Also I think if the business logic is too complex, then it's time to divide your logic and View. – zwcloud Jun 17 '20 at 03:48
  • in an MVVM project every file you have belongs to one of the 3 components, M, V or VM. So that service layer is also a part of M (model). – Rukshan Mar 19 '22 at 15:10
26

The Model's purpose is to represent (or model) your business domain. Therefore, business logic by definition goes in the Model, not the ViewModel.

The job of the ViewModel is to expose properties and fields of the Model, and prepare them for consumption by the View.

For instance, picture a banking application. The Model may represent an account. Perhaps the Model has an account balance. The job of the Model may be to track the balance and make sure certain invariants are maintained (such as not allowing a withdrawal that is larger than the balance). The job of the ViewModel may be to turn the balance into a string that is used as a binding in the View.

You want to keep as much logic out of the ViewModel as possible to keep your code reusable and loosely coupled.

bodangly
  • 2,473
  • 17
  • 28
  • 13
    I disagree with this. A model should ideally only have properties because models represent the data. A ViewModel is an _ok_ place for BL. I'd keep the BL outside the models and the ViewModels as far as possible. As for your last statement, that is more true for Models than ViewModels. ViewModels by definition are tightly coupled to Views. – galdin Oct 29 '17 at 06:45
  • 2
    @gldraphael ViewModels by definition is not tightly coupled to Views. ViewModels came out from MVP for loose coupling to Views by observer pattern and Data Binding – Wood Jan 18 '20 at 04:00
  • 8
    @david I do have different opinions now. Business logic belongs in the domain model. Seems like back in 2017 i was thinking of EF models aka DAO or data model classes. – galdin Jan 18 '20 at 07:02
1

Use the model if you are building a web app; and one level bellow the model i.e. the domain level if you are building a LAN/desk app.

Your problem - re-calculate costs after an asset has been re-valued - might not just be a user interface issue. A back-end application might want to do the same (for example, for automatically importing data). And then you have a choice of either duplicating business logic or rewiring to existing one.

Nothing wrong with using the same model for the back-end too. But models -especially disconnected ones- tend to be large data structures because they need to bring with them all data from reference tables (unless you want to do round trips to server and sacrifice your GUI experience). And that might affect performance if model is used.

Tomaz Stih
  • 529
  • 3
  • 10
0

if you model contain required data for calculation you can use model.if model does not contain the data means create view-model and get data to do the calculation.(With respect to Business logic )

if you want to pass this data to view create View Model It improves code re-use opportunities

MMM
  • 3,132
  • 3
  • 20
  • 32