4

Ok, I'm not talking about making business logic decisions, but rather UI decisions.

For example, I'm rendering a table and one column displays a DateTime? property that needs to be formatted. Because the value is nullable I need to check that it's not null before formatting.

If I wanted to be pedantic, I would have a FormattedDate property on my ViewModel:

public class MyViewModel 
{
    ...
    public DateTime? Date { get; set; }

    public string FormattedDate 
    {
        get 
        {
            return this.Date.HasValue ? this.Date.Value.ToShortDateString() : "";
        }
    }
}

<%= Html.Encode(Model.FormattedDate) %>

Or I could save myself a few lines of code and simply slap it in the view:

<%= Html.Encode(Model.Date.HasValue ? Model.Date.Value.ToShortDateString() : "")%> 

In this case, since this is something that only affects the view, I would argue that it's OK to do it the second way (and also it's more compact) but where do I draw the line between having my view cluttered with server-side code and having my ViewModel cluttered with "formatting" properties?

Veli Gebrev
  • 2,481
  • 4
  • 31
  • 48

2 Answers2

4

It doesn't really save you any lines of relevant code if you put it directly in the View - it just moves it around.

However, if you put it in the View, you can only use it there. You can't reuse the ViewModel's logic elsewhere, and you can't unit test it.

Keep your Views really dumb. I would say that Views should have as low a Cyclomatic Complexity as possible.

See this answer for more details.

Community
  • 1
  • 1
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Well that settles the question of whether the view should have any logic in it - NO. As far as where the logic should go is concerned - I'm leaning towards using formatting extension methods as suggested by David M - makes the logic testable and de-couples it from a specific ViewModel (of course I can totally see other scenarios where it's more domain object specific than formatting a date, so it would have to go in the ViewModel itself) – Veli Gebrev Jan 06 '10 at 12:08
  • 1
    Although the extension method may be testable, the View is not, which means that you will have no unit test that verifies that it is correctly invoked from the View. I think you would be breaking the principle of Cohesion by implementing some of the View in extension methods, and some of it in the ViewModel. Putting it all in the ViewModel will give you higher cohesion while following the Single Responsibility Principle. – Mark Seemann Jan 06 '10 at 12:17
1

If it's something you do a lot, perhaps you could write an extension method for Nullable<DateTime> like so:

static public string Format(this DateTime? value)
{
    return value.HasValue ? value.ToShortDateString() : string.Empty;
}

Saves cluttering your ViewModel or your View.

David M
  • 71,481
  • 13
  • 158
  • 186
  • yeah, that's a good option, in my case it's a bit of an overkill but will keep it in mind for future reference :) – Veli Gebrev Jan 06 '10 at 11:41