With current practices (at least with WPF and Silverlight) we see views bound via command bindings in the view model or we at least see view events handled in view models. This appears to be a violation of SRP because the view model doesn't just model the view state, but responds to the view (user). Others have asked how to build view models without violating SRP or asked whether their implementations do so (this last is the controller in MVC, but roughly analogous).
So are current practices a violation of SRP? Or is "view model" really a collection of things that don't violate SRP? To frame this a bit, it seems we need to know what is the single responsibility or if there are multiple responsibilities in the concept, are the individual responsibilities split out, conforming to SRP. I'm not sure.
Wikipedia's definition of view model says
[T]he ViewModel is a “Model of the View” meaning it is an abstraction of the View that also serves in data binding between the View and the Model
This seems good enough for SRP, but then the entry later says (my emphasis added)
[The ViewModel] acts as a data binder/converter that changes Model information into View information and passes commands from the View into the Model
In a Prism blog post about the view model's role, the author says (again, my emphasis)
What it boils down is that the view model is a composite of the following:
- an abstraction of the view
- commands
- value converters
- view state
I'm sure I've missed many definitions out there, but they seem to fall into these categories:
If you're curious, I "care" about this because (2) feels right, but seems counter to the prevailing implementations.
For example, if we have a class that we change a lot, and for different reasons, then this class should be broken down into more classes, each handling a single concern.
The Single Responsibility Principle (SRP) The idea behind the SRP is that every class, module, or function in a program should have one responsibility/purpose in a program. As a commonly used definition, "every class should have only one reason to change".
Benefits of Single Responsibility PrincipleWhen an application has multiple classes, each of them following this principle, then the applicable becomes more maintainable, easier to understand. The code quality of the application is better, thereby having fewer defects.
The purpose of ViewModel is to encapsulate the data for a UI controller to let the data survive configuration changes. For information about how to load, persist, and manage data across configuration changes, see Saving UI States.
Single Responsibility as Martin defines it:
"THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A CLASS TO CHANGE."
A ViewModel, as far as MVVM is concerned is really just a specialized implementation of a Presentation Model.
So while it could be argued that a Presentation Model should only represent the state of the UI, and that a Presenter/Controller should always broker the commands between the UI and the Presentation Model. If one follows this idea, with SRP dividing on State and Commands, then adding a command should not affect the class that represents state. Therefore MVVM would break SRP.
I think this is grasping at straws. MVVM is a fairly specialized implementation used basically in WPF/Silverlight (and now browser clients).
Patterns are designed to make designs simpler where the alternative would be more cumbersome or less maintainable. Since MVVM is designed to take advantage of the extremely rich data binding capabilities of the presentation technologies, then it is a worthwhile trade off.
No! MVVM does not violate SRP, (the programmer does, lol!)
There is no reason that using the MVVM pattern needs to ignore the SRP. MVVM does not mean that there is only one Model Class, one View-Model Class, and one View Class. Certainly, if you only had one View Class, you could only ever show one simple screen.
Those classes that are in the View tier, should be responsible for one thing; doing, deciding, or containing. A View can consist of several sub-views who's jobs are to do certain pieces of the users interractions. Consider a basic form, it has a display grid, items in the grid can be edited, and there is a "Save" button.
The main View would be a container for two other views; the datagrid (a user control, or something) and a command control. The datagrid then is responsible for choosing the right childview to render data in; in essense it's a container that databinds. The View to edit items is a child view of the datagrid, which is in-turn a child of the main View. Lastly the command control is a set of buttons (in this case a single one) who's single responsibility is to raise signals that commands have been issued by the user.
In this way the Edit View (used by the DataGrid) is agnostic about what uses it, and has one responsibility; Same with the command control. Likewise the DataGrid doesn't care about who uses it, only that it can contain the Edit View (child). Nice SRP there.
ViewModels to match the Views (and children) are also responsible for one thing. The Edit View Model is a container to which the Edit View Binds; it simply contains the data fields that can be displayed/edited. It doesn't care about anything but signalling when one of its properties change. The Command Button View Model is a class that does things. It's commands are bound to the buttons, and it will do work based on what the user clicks on. It will have to have access to other parts of the ViewModel(s) to do it's work.
The main page View Model is there to contain the other child views. It's sole responsibility is as an initializer, making all the required ViewModel instances, and passing constructor parameters to other ViewModel instances (say, the Command Button View Model so it knows where to get data for it's work)
It's natural to cram a whole bunch of functionality into a single ViewModel that a large View would bind to. But it doesn't have to be that way, and SRP can be maintained in MVVM.
The main goal of MVVM is to allow for testable design, the Model layer can be tested independantly, all classes in the Model can easily follow SRP. The ViewModel can be tested without the need of a view; it gets trickier to think SRP in the ViewModel, but it is certainly doable; just remember to break out your classes so they only have one concern. The View is bound to parter ViewModels, with any luck, your testing of the ViewModel makes snapping the View(s) on super easy. Remember you can have each View-let adhere to SRP to be part of a larger conglomerate View (container).
TL;DR? To answer your question directly, the View is a collection of classes that does not break the SRP. Thus, when the ViewModel is abstracted from the View(s) (View-First), they are also a collection of classes that adhere to good SRP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With