MVC granularity

I've recently been looking into MVC patterns, and I'm quite surprised by their variety. The big issues I had missed before was that SmallTalk didn't follow the now classic Forms and Controls model. In its case their were objects that displayed UI and objects that handled input, or views and controllers. Martin Fowler has of course done a great job of differentiating these GUI architectures into several patterns, including SupervisingController and PassiveView. In addition we can consider Classic MVC, Application Model MVC and at least two forms of MVP. Aviad has done a good job of describing all these so I won't do him the disservice of repeating his work.

What strikes me as interesting is that the most favoured pattern here seems to be PassiveView. This pattern comes up again and again and again.

Granularity

One thing I don't see being mentioned is the granularity of a model-view update. Should an update occur on only a single property, or when an entire set of change is propagated. Consider the following models

Fine updates

image

Word is a great example of MVC in action. Here I have highlighted the Font characteristics for the selected text being displayed in three views. I can change the properties in any number of ways and they will always show the correct information in all three locations.  In this case changing the values in the toolbar results in an immediate change to the other views of those values.

 

Coarse updates

image

The alternative to updates with every property is to update on mass, and in fact we see dialogs where this appears to happen already. Here we see a Cancel button. You can make as many changes to the settings in this dialog as you like, but none of them will get propagated back to the main model unless you press OK.

Forms and controls

As already pointed out MVC was originally developed for SmallTalk, there are pitfalls when you migrate to a standard WinForms world with Controls.

Cascading updates

image

Sample code Demo1

Consider this user interface. It has two views of the same data. Change the data in one view and the 2nd should get updated. It works as you expect by using an event on the control to trigger this process off.

image

  1. Event triggered in Form, Form tells view that a change has occurred.
  2. View tells controller that a change has occurred
  3. View records change in Model then tells each view to update its model
  4. View updates from Model and updates the control.

Unfortunately what happens is that the other view then triggers a change event as well so we end up with the model being updated again. You can see this if you run the attached project in the debugger, and watch the Output Window.

model updated by View2
model updated by View1

Fortunately the update is stopped from cascading indefinitely by the fact that the data doesn't really change in the control, it's just to the same value again in the control so no xxxxChanged event is fired.

Missing updates

This problem gets worse with larger granularity. Given what we have seen above, consider where we have multiple views and a model with multiple properties

image

  1. The controller updates all views and sets the first property of a view causing a changed event to occur
  2. The control event triggers a view update, the view calls the controller
  3. The controller updates the model, which overwrites the 2nd property
  4. The controller updates all views
  5. The controller sets the first property on the views, but since this value has already been passed to the view, it doesn't trigger an event
  6. Updates complete, there are no more changes that trigger events
  7. The 2nd property can now be updated in all views, but it will not be the value that we expected

To avoid these issues

Since all UI updates have to be done in a single thread, the if we use a BeginUpdate(), EndUpdate() pair in the View, that wraps the update of the controls property we can discard the the changed event from the control.

Dynamic Granularity

Looking at WPF we can see that it uses the INotifyPropertyChanged interface to handle its updates and that basically relies on PropertyChangedEventArgs with its single piece of data,

 
namespace System.ComponentModel
{
    // Summary:
    //     Provides data for the System.ComponentModel.INotifyPropertyChanged.PropertyChanged
    //     event.
    public class PropertyChangedEventArgs : EventArgs
    {
        // Summary:
        //     Gets the name of the property that changed.
        //
        // Returns:
        //     The name of the property that changed.
        public virtual string PropertyName { get; }
    }
}

If we modify the controller-view registration process we can ask each view to register only for the properties of the model that it is interested in receiving updates for, and therefore update when only a subscribed property changes. This can significantly reduce the amount of updates that are propagated. In the following example only 2 of the 5 views will be notified when the bold state changes.

image

Links

Martin Fowler

ASP.Net MVC

Comments (2) -

Marchel
Marchel
10/5/2008 8:47:22 AM #

Hן Alski,

I've enjoyed your article a lot, 10x

I am looking for good explanation about 'Application Model MVC' that you wrote about, You wrote about the first variations of MVC but didn't supply link to the details.

Thanks,

alski
alski
10/5/2008 8:09:41 PM #

Thanks for the feedback Marchel. I've updated the article with the link but just in case, see
aviadezra.blogspot.com/.../...y-hello-to-mvpc.html

Comments are closed