views:

112

answers:

2

In several sample projects, I've seen ViewModels being used to convert data objects into strings, for use in the View.

The ViewModel will typically have a constructor that receives one parameter - a data object. The constructor will then populate various properties of the ViewModel (mostly strings and ints).

This prevents any complex logic from occurring in the View.

At first glance, this seems like a good idea to me, as it more fully enforces separation of the View from complex logic.

For example, say my view was trying to render a property 'Size' of a data object, Size being a number between 1 and 3 representing 'Small/Medium/Large'.

Instead of having a if/switch statement in my view, I would just have a 'SizeString' or something similar in my ViewModel, and the if/switch statement would go in the ViewModel constructor.

Does anyone disagree with this approach?

Would it be better to use some other approach, such as helpers? And if so, why?

+2  A: 

It converts everything to string because everything in web is a string.

Basically - view model is supposed to be in 'ready to output' state. If web were made from numbers only - we would transform everything to ints/decimals.

Whole point of viewModel - to format data representable. In your case - size enum to small/medium/large. It's not that detaching logic from views makes this valuable - it's ability to adept your data for web in one way, one place.


Answering to comment =>

Yeah, that sits well. I'm doing the same. But thing to mention - I'm not against putting that into views too. Because views and view models are last in 'dependency chain'. I'm quite pragmatic and completely against only to situations when developer uses domain model as view model and requirements for view model gets in conflict with domain model (i.e. when developer adds new "domain objects" for representational purposes only).

Arnis L.
Actually I already implemented it as an Enum, but I excluded that fact so as not to overcomplicate the example. Of course, if I just let the View directly access the Enum, there's still going to be some logic to convert it to a string, like so: "Enum.GetName(...)". So I would still prefer to expose the property as a string in the ViewModel, and let the ViewModel take care of the enum-string conversion. Would this sit well with you?
jonathanconway
updated my answer...
Arnis L.
+5  A: 

The purpose of the ViewModel is to represent (a part of) the complex Domain Model decomposed as primitives that can be rendered in some form other other.

This decomposition must take place somewhere. It may involve some simple kind of logic, such as my favorite example: converting a discreet value (OK, warning, error) into colors (Green, Yellow, Red). This is the essence of what a ViewModel does, so my default approach would be to encapsulate this logic into the ViewModel itself.

Consider the alternative: If not implmented in the ViewModel, then where? If you put the logic somewhere else, you end up with a ViewModel that's basically just a structure without logic. Letting a ViewModel encapsulate the transformation/decomposition of a Domain Object fits well with the Single Resposibility Principle.

Although this is my default appraoch, I'm always aware that the logic may need to be reused across multiple ViewModels. In such cases, this may be an indication that the original ViewModel is really a complex ViewModel made up of several sub-views. In such cases, you can extract the common logic into a sub-ViewModel that encapsulates only that little part.

Mark Seemann
Good explanation. The reason I was unsure about this was that I'm sure I read somewhere that ViewModels should just be plain POCO objects without any logic. But clearly this wouldn't work. The ViewModels should be allowed to contain presentation logic.
jonathanconway
POCO doesn't exclude the existence of logic :)
Mark Seemann
Wanted to write about SRP, but you already did that. As i always say - it's hard to be a boxer and ballet dancer simultaneously. :)
Arnis L.
We've found that it's easier to create ViewModels be POCOs that correlate 1-1 with view controls/data, then put all mapping/transformation logic in separate mapper classes. This allows for better re-use of the simple mapping, while also reducing the chance that a developer will start putting more complex calls in the view (the only function calls we make are to the Html helper classes).
Jess
Interesting idea. I've also heard of duplicating properties from the domain object, and then using a framework such as "AutoMapper" to automatically shift the data from the domain object to the ViewModel.
jonathanconway