Monday, February 21, 2011

My take on MVVM, I like to add a "C" so we get MVVMC

There is a lot on the web about the Model-View-ViewModel (MVVM) pattern. To me, overall, it seems like a great way to go for developing testable, extensible user interfaces. However, I have run across a few areas where I'm not in total agreement, and other areas where I just think MVVM blogs just gloss over details of things that I think are really important. In my next few blog posts, I hope to outline how I see MVVM and how I have chosen to implement it. I may not be correct in everything, but I hope to present a direction to go for development.

My ultimate goals are to develop code that is consistent, easy to read and follow, and hopefully automatically testable via unit testing or other automation.

The first thing I propose doing is removing control logic from the ViewModel. In most MVVM implementations, you see the VM containing the control logic, for example, if a "Save" button is clicked, we see the VM responding to the command and writing the data to the database. I don't like this. It's not that having it in the VM is a bad thing, it is encapsulated and away from the view. But to me the VM should be light weight, responsible only for transforming model data into a data format easily digestible by the view and for gathering user input back from the view.

By moving control logic, validation, etc. into a controller class, this allows the view model to focus on it's job, makes it easier to read, and I think makes it easier to test the controller.

Here is a diagram of my structure.  Unlike most MVVM models, I take into account using MVVM on custom controls as well as Main UI windows.   Designing a custom control (that derives from User Control) and using the MVVM pattern requires departure from the traditional MVVM pattern.


In looking at the model, we see a departure from the classic MVVM model where the view only accesses only the ViewModel.  If the setup is for a top-level window, and not a control, then things become just like the classic MVVM model.

But when making a user control, their are things that belong to the view in the WPF world and we really need them to notify the controller.  Dependency properties are a prime example of this.  They are attached to the code-behind of an XAML file, which really belongs to the view.  In this case, the view needs to inform the controller module that a dependency property has been updated and let the controller respond appropriately.  And the controller needs to inform the view when a dependency properties value should change.  If we are not working on a user control, then everything goes back to normal MVVM where the view has no knowledge of the controller or view model.

However, if we look at a dependency diagram, I think the view have knowledge of the controller is OK.   After all, dependencies still only go one way and this is fine.  It still allows us to replace the view with a unit test and not have anything break.




It is this important that dependencies flow one way.  This is critical for being able to test and for a clean architecture.  The View has knowledge of the ViewModel and possible the Controller.  The Controller and possible the ViewModel has knowledge of the Model.  In this model, the View can be replaced without the knowledge of any of the underlying layers.

Messaging up the chain takes place via events.  If the ViewModel needs to notify the View of changes, this is accomplished by raising an event and allowing the View to listen for it.  The WPF way of doing this is to use the INotifyPropertyChanged interface. 


 It is critical to use interfaces whenever possible.  An interface allows us to swap out components with testable components.  An interface between the ViewModel / Controller and Model allows us to unit test the ViewModel / Controller by creating a mock model. 


In developing the ViewModel and Controller, it is critical that these classes be separated from any UI components, including opening new windows.  Every action within the view model and the controller should be completely contained.  Opening a new window would be instantiating another view, which violates the requirement that the ViewModel and Controller have no knowledge of the View.  Additionally moving things on and off the UI thread is something that belongs in the domain of the View.  However, often it is the Controller that makes this move.

In order to accomplish application tasks, such as opening new windows and putting things onto the UI thread, interfaces should be created to concrete classes responsible for operating in the View space.  This configuration allows these objects to be mocked out during unit testing.  This will be the subject of a future blog post.

I hope to put some example code up soon as well. 

Monday, January 3, 2011

Using Nested classes to encapsulate View Models in User Controls

I have been working on developing some more complex user controls that will serve as the base of a lot of applications we develop. These controls will exist in a separate library of common controls. Although I am not using Prism, this is following in line with the composite concept the present, having an application being composed of many different reusable user controls.

I like the MVVM pattern and have made extensive use of View Models within the control.  However, I do not want to really show all those "internal" view models to the users of the control.  Unfortunately, traditional hiding techniques, such as internal classes are not allowed by WPF.  To solve this problem, I employed a few tricks.

1.  Declare the constructor as internal on the public class.  This prevents the applications from initializing their own instances of View Model and protects against others using your classes.  This means you can more freely upgrade and modify your class as the internal needs of your control change without worrying about breaking someone else's code.

2.  "Hide", or at least partially hide all the "guts" of the control by putting them inside the user control class as embedded classes. When doing this, I like to have each View Model in its own file.  I learned long ago that one class per file is a good rule to follow.  To do this, I use the handy partial class feature.

Now, these two methods don't always work.  If you directly reference the View Model from the XAML, you have to make the class public. You can see the requirements for classes used within XAML here.   However, in my case many of my view models are only instantiated in code and returned via properties (like lists of items, etc).  In fact, only one of my View Models needed to be made public.

Here is an example of a control's View Model. It can't be instantiated outside the control's assembly (aka, the app using it) and the class is at least somewhat hidden from view. For example, Intellisense won't show all the class names unless someone actually types out "MyUserControl.".


public partial class MyUserControl
{
  public class MyViewModel
  {
     internal MyViewModel() { }
  }
}