Search code examples
wpfmvvmreactive-cocoa

MVVM design choice regarding responsibility of ViewModel for simple states


I've recently started to delve into MVVM architectural pattern. I've understood large parts of it but still few doubts remain regarding how much responsibility ViewModel should take on behalf of View.

In other words, how dumb should View be?

For example, for simple state coordination like clearing TextView after user presses SubmitButton. This kind of state coordination requires no more than one-liner to implement using some of the popular data-binding frameworks.

For example in pseudo-ReactiveCocoa:

textView.text <~ submitButton.pressed.map { _ in "" }

However, Martin Fowler wrote in his Presentation Model,

The Presentation Model contains the logic that says that the composer field is only enabled if the check box is checked, so the when the view updates itself from the Presentation Model, the composer field control changes its enablement state

which suggests that even the simple logic like clearing out TextView after pressing Button should be encapsulated inside ViewModel.

Such design choice leads to something like this (again, in pseudo-ReactiveCocoa):

// In View
viewModel.submitButtonPressed <~ submitButton.pressed
textView.text <~ viewModel.textViewText

// In ViewModel
textViewText <~ viewModel.submitButtonPressed.map { _ in "" }

Although it leads to better encapsulation of logics while assuming view with the job of binding only (making it dumb), it does make code a lot more verbose and lead to tighter coupling between View and ViewModel (by requiring ViewModel to be aware of SubmitButton).

I'm still new to MVVM pattern in general and learning stuff every day.

How much responsibility should ViewModel take?

In other words, must View be completely dumb and only handle simple binding (connect its UI elements to bindable property provided by ViewModel) or is it okay for View to handle fairly simple logic like the above?

On a side note, is tight coupling between View and ViewModel okay in MVVM?


Solution

  • In general, the ViewModel takes all responsibility. More specifically, in your scenario, the ViewModel wouldn't know about the submitButton, but rather the View would know that the ViewModel exposes a command (an ICommand) called SubmitCommand, and have the submitButton bind to that command.

    Sometimes it can get a bit more involved to completely separate the actions and corresponding logic, for instance when there's no binding available for a command for a specific event. But in those cases a fairly simple attached behavior (i.e. InvokeCommandAction and friends, see the documentation) can bridge that gap to coax flow so the logic can go in to the ViewModel.

    Very rarely, there are scenarios (of which none come to mind currently) where it gets so involved that I just skip the whole idea, and separate as much as possible, rather than to have to work out three months later exactly what the hell is going on. But those cases are rare indeed.