Silverlight

The MVVM Pattern Is Highly Overrated

102 commentsWritten on July 21st, 2010 by
Categories: Architecture, Code Quality, Silverlight

Update: check out my MVP In Silverlight/WPF series which discusses the MVP approach as an alternative to MVVM

If you're doing Silverlight or WPF, you've no doubt come across the MVVM (Model-View-ViewModel) pattern. It seems to be the most popular client-side architecture pattern used among Silverlight/WPF developers. I find the pattern to be highly overrated, and actually have some big issues with the whole thing.

First, let's briefly cover what MVVM is about for those of you who don't know yet. MVVM virtually eliminates all of the code that would typically be placed in the code-behind file of your View (a user control, a screen, whatever) by putting all of that logic in the ViewModel. The ViewModel itself is never tightly coupled to the View. If it does have a reference to it, it's typically through an interface that the View implements instead of a reference of the actual type of the View. This increases, or better yet, introduces testability to a large part of your UI code that you normally wouldn't be able to cover with unit tests if you'd go with the traditional "put it all in the code-behind"-approach.

The ViewModel typically contains properties for the data that is to be shown in the View, and also raises notification events when the data in those properties changes. The View uses the powerful data-binding capabilities of Silverlight/WPF to bind the properties of the ViewModel to other user controls that the View is composed of. User-events that are captured by the View are sent to the ViewModel through Commands. Typically, these commands execute a method in the ViewModel which contains some kind of logic... usually to either send the updated data in the ViewModel's properties to the Model (usually a Service Layer in Silverlight, in WPF it could be either a true Domain Model or also a Service Layer), to perform some business logic in the Model, or to retrieve data from the Model so it can be placed in the ViewModel's properties so the View can bind to it.

That is, in a nutshell, how the MVVM pattern works. So why do i have issues with this? You can develop and test most of the application's logic without being dependent on a physical View and that is typically a Good Thing, no? It sure is! However, my problem with this approach is that too many responsibilities are concentrated within the ViewModel. Its main responsibilities are to facilitate databinding and to interact with the Model. And that, in my opinion, isn't very clean. In some ways, you could actually think of the ViewModel as a glorified code-behind, with the only difference being that it's not tightly coupled to the (physical) View.

In most (if not all) MVVM implementations, a ViewModel has many possible reasons to be changed. It might need to be changed because of different data-binding requirements. Then again, it might also require changes when a part of the Model is modified. Now, i'm sure many of you can agree with me when i say that two of the most important principles in software development are Seperation of Concerns (SoC) and the Single Responsibility Principle (SRP). Obviously, the ViewModel doesn't fare well when it comes to both of these principles.

Lets forget about MVVM for a second and focus on the concerns and responsibilities that a user control can have... say, a user control that shows customer information and allows the user to edit that data so it can be persisted:

  • visualization of the actual control (its own layout as well drawing other user controls that it is composed of)
  • communication/interaction with the Model
  • making data (from the Model) available so it can be displayed
  • outputting data in the correct user controls (for instance: various textboxes)
  • (simple validation) of modified/inputted data (for instance: no string values for numeric fields, etc...)

Without MVVM, all of these would be taken care of in the View. Obviously, not a good idea right? After all, if it were a good idea, we'd never have had a reason to start using MVVM in the first place.

Now, with MVVM, a lot of people would divide these concerns and responsibilities like this:

View:

  • visualization of the actual control (its own layout as well drawing other user controls that it is composed of)
  • outputting data in the correct user controls (for instance: various textboxes)
  • (simple validation) of modified/inputted data (for instance: no string values for numeric fields, etc...)

ViewModel:

  • communication/interaction with the Model
  • making data (from the Model) available so it can be displayed

In this case, the View still has 3 responsibilities which is still too much according to 'the guidelines', but it's not that big of a deal (though plenty of people would argue that the simple validation would be better placed in the ViewModel). You're highly unlikely to actually want to write automated tests for pure visualization anyway and the SRP is not something that you absolutely need to follow to the extreme in every single place. For the View, this is really not a problem and very much acceptable.

The ViewModel however has 2 important responsibilities in this case, and i'd argue that these 2 things should not be done in the same place. Making data available is done through data-binding. To do this, you need a set of properties and you need to raise the necessary events. In most cases, raising those events is very straightforward, but in more complex controls you might need a bit of additional logic to determine which event should be raised at what point. The other important responsibility is the communication/interaction with the Model. In most Silverlight applications, the Model will be a Service Layer. To communicate with this Service Layer, you need Service Proxies. That means that your ViewModel is essentially responsible for communicating with the Service Layer, dealing with business exceptions that might be thrown by some service calls, and dealing with technical exceptions that can occur simply because of network-related problems. Group all of those together and i don't think i'm going out on a limb here by saying that that is a lot of logic to put in one class, no?

(Sidenote: what i don't really understand is that many people who vigorously advocate adherence to SRP and SoC in their domain and business code don't seem to hold their UI code to the same standards. I do.)

At work, we do a lot of Silverlight development. We typically have around 5 Silverlight projects in active development at the same time. And it's been that way for over a year now. That equals a lot of Silverlight code that we've written and experience and knowledge that we've built up. And we haven't used MVVM for any of it. All this time, we've been using the MVP pattern (Supervising Controller variant) with a slight twist. That twist being a slimmed down version of a Presentation Model. Our Presentation Model's sole responsibility is to facilitate data-binding, and in some cases, a touch of validation is added as well.

If we go back to our previous example of the customer screen, the responsibilities and concerns would be divided like this in our MVP-PMlight approach:

View:

  • visualization of the actual control (its own layout as well drawing other user controls that it is composed of)
  • outputting data in the correct user controls (for instance: various textboxes)
  • (simple validation) of modified/inputted data (for instance: no string values for numeric fields, etc...)

Presenter:

  • communication/interaction with the Model based on the contents of the Presentation Model

Presentation Model:

  • making data (from the Model) available so it can be displayed

Which leads to classes which are more focused on their task instead of trying to focus on too many things at the same time. In my opinion, this approach is much better/cleaner than MVVM. Not only is there a noticeable benefit in code quality (classes are more focused), there is also increased potential to reuse our 'light Presentation Models' in multiple controls. Testability is increased over MVVM as well since it's always easier to test classes which are focused versus testing classes which have too many responsibilities. All in all, a couple of important benefits and we still haven't thought of a real drawback compared to MVVM.

Introducing AgUnit: Silverlight Unit Testing With Resharper

2 commentsWritten on May 31st, 2010 by
Categories: resharper, Silverlight, testing

A couple of months ago, i showed a sneak preview of a Silverlight unit testing Resharper plugin that one of my coworkers was working on.  I’m glad to say it’s finally been released and you can get it here :)

agunit

Those are Silverlight tests, executed through Resharper within the Silverlight runtime :)

Unit Tests And Silverlight

9 commentsWritten on December 16th, 2009 by
Categories: Silverlight, testing

Capture

This is something that Steven De Kock and Tom Ceulemans (two coworkers of mine without a blog, so no link) have been working on.  Those are Silverlight tests, executing in the Silverlight runtime, within a full browser context.

And yes, they will release it as an open source project soon :)

Integrated Security With Silverlight And WCF

1 Comment »Written on November 3rd, 2009 by
Categories: Silverlight, WCF

I lost some time yesterday trying to get a Silverlight client to use Integrated Security with a WCF service so i figured i'd post the steps necessary to make it work here.

First of all, you need to make sure that your IIS installation has support for Windows Authentication. Go to Add/Remove Programs (appwiz.cpl), click on Turn Windows Features on or off, select Internet Information Services - World Wide Web Services - Security and make sure that Windows Authentication is checked.

Next, you need to make sure that the virtual directory where you're hosting the WCF service has Windows Authentication enabled. Open Internet Information Services Manager (inetmgr), select the virtual directory where the WCF service is hosted, click on the Authentication icon and enable Windows Authentication.

After that, you need to add the following to the binding configuration of the service endpoint (in the host, obviously):

          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" />
          </security>

I only got it working with basicHttpBinding, so unfortunately i can no longer use the customBinding to use binary XML...

In your Silverlight project, open the ServiceReferences.ClientConfig file and add the following to the binding configuration:

          <security mode="TransportCredentialOnly" />

After that, you should be able to do this in your WCF service:

            WindowsIdentity myuser = ServiceSecurityContext.Current.WindowsIdentity;

And that should return the Windows user of the user running the Silverlight client.

For the record: this is with Silverlight 3... i have no idea if it'll work with Silverlight 2

Event Aggregation

7 commentsWritten on October 9th, 2009 by
Categories: Patterns, Silverlight

We're experimenting at work with a bit of a different approach as to how we structure our views and how they will interact with each other. We already know that our views will be reused in many different contexts so having them communicate with other views is something that needs to be done in a very loosely coupled manner. I don't want any of the views to even know about the existence of other views, let alone having them know about specific instances of them.

But these views do have to interact with each other. I didn't want to use typical events because that would require either a certain view to know about another view to be able to subscribe to its events, or you'd need some other component which knows which views need to be hooked to each other. We really need maximum flexibility for what we have in mind with our views, so it only made sense to finally start using the Event Aggregation pattern. The idea is that a view can basically publish events, without knowing who is subscribed to these events, and that suscribers will be notified whenever these events occur. However, subscribers don't know anything about who is publishing the events. Instead, both publishers and subscribers only know of the Event Aggregator. A publisher tells the aggregator to publish an event to all subscribed listeners for that event. Each subscribers simply tells the aggregator "i'd like to be notified whenever this event occurs, and i don't care where it comes from".
Plenty of implementations of this pattern can be found online already, so i figured: why not add my own? :p

Fist of all, an event is nothing more than a class that inherits from this class:

    public abstract class Event {}

Every event should inherit from this class, and add whatever necessary properties that are important for that particular type of event.

If a class is interested in listening to a specific event, it needs to implement the following interface:

    public interface IListener { }
 
    public interface IListener<TEvent> : IListener
        where TEvent : Event
    {
        void Handle(TEvent receivedEvent);
    }

If a class is interested in multiple events, it simply needs to implement the generic IListener interface for each type of event that it wants to handle.

Then we obviously need the Event Aggregator. I wanted an aggregator that allowed listeners to either subscribe/unsubscribe to/from very specific events, or just subscribe/unsubscribe to/from whatever it supports. So i have the following IEventAggregator interface:

    public interface IEventAggregator
    {
        void Publish<TEvent>(TEvent message) where TEvent : Event;
        void Publish<TEvent>() where TEvent : Event, new();
 
        void Subscribe(IListener listener);
        void Unsubscribe(IListener listener);
 
        void Subscribe<TEvent>(IListener<TEvent> listener) where TEvent : Event;
        void Unsubscribe<TEvent>(IListener<TEvent> listener) where TEvent : Event;
    }

The Subscribe and Unsubscribe methods that simply take an IListener reference will either subscribe or unsubscribe the given listener to/from every event that it can handle. In other words, for every generic IListener interface that it implements. Yet you also have the ability to subscribe/unsubscribe from a specific event type.

And here's the implementation:

    public class EventAggregator : IEventAggregator
    {
        private readonly object listenerLock = new object();
        protected readonly Dictionary<Type, List<IListener>> listeners = new Dictionary<Type, List<IListener>>();
        private readonly IDispatcher dispatcher;
 
        public EventAggregator(IDispatcher dispatcher)
        {
            this.dispatcher = dispatcher;
        }
 
        public virtual void Subscribe(IListener listener)
        {
            ForEachListenerInterfaceImplementedBy(listener, Subscribe);
        }
 
        public virtual void Unsubscribe(IListener listener)
        {
            ForEachListenerInterfaceImplementedBy(listener, Unsubscribe);
        }
 
        private static void ForEachListenerInterfaceImplementedBy(IListener listener, Action<Type, IListener> action)
        {
            var listenerTypeName = typeof(IListener).Name;
 
            foreach (var interfaceType in listener.GetType().GetInterfaces().Where(i => i.Name.StartsWith(listenerTypeName)))
            {
                Type typeOfEvent = GetEventType(interfaceType);
 
                if (typeOfEvent != null)
                {
                    action(typeOfEvent, listener);
                }
            }
        }
 
        private static Type GetEventType(Type type)
        {
            if (type.GetGenericArguments().Count() > 0)
            {
                return type.GetGenericArguments()[0];
            }
 
            return null;
        }
 
        public virtual void Subscribe<TEvent>(IListener<TEvent> listener) where TEvent : Event
        {
            Subscribe(typeof(TEvent), listener);
        }
 
        protected virtual void Subscribe(Type typeOfEvent, IListener listener)
        {
            lock (listenerLock)
            {
                if (!listeners.ContainsKey(typeOfEvent))
                {
                    listeners.Add(typeOfEvent, new List<IListener>());
                }
 
                if (listeners[typeOfEvent].Contains(listener))
                {
                    throw new InvalidOperationException("You're not supposed to register to the same event twice");
                }
 
                listeners[typeOfEvent].Add(listener);
            }
        }
 
        public virtual void Unsubscribe<TEvent>(IListener<TEvent> listener) where TEvent : Event
        {
            Unsubscribe(typeof(TEvent), listener);
        }
 
        protected virtual void Unsubscribe(Type typeOfEvent, IListener listener)
        {
            lock(listenerLock)
            {
                if (listeners.ContainsKey(typeOfEvent))
                {
                    listeners[typeOfEvent].Remove(listener);
                }
            }
        }
 
        public virtual void Publish<TEvent>(TEvent message) where TEvent : Event
        {
            var typeOfEvent = typeof(TEvent);
 
            lock (listenerLock)
            {
                if (!listeners.ContainsKey(typeOfEvent)) return;
 
                foreach (var listener in listeners[typeOfEvent])
                {
                    var typedReference = (IListener<TEvent>)listener;
                    dispatcher.BeginInvoke(() => typedReference.Handle(message));
                }
            }
        }
 
        public virtual void Publish<TEvent>() where TEvent : Event, new()
        {
            Publish(new TEvent());
        }
    }

In case you're wondering... the IDispatcher interface is merely a way to wrap Silverlight's real Dispatcher. We wrap it so we can use a different implementation of the IDispatcher in our automated tests. Other than that, the implementation is very straightforward.

We started using this very recently, so this implementation might change in the upcoming weeks, but for now it does what it needs to do and it does so pretty well. In our case, every view's Presenter automatically has an IEventAggregator property so whenever we need to publish an event, we can simply do something like EventAggregator.Publish(new SomeEvent(someParameter)). Or, Presenters that need to listen to events can simply say EventAggregator.Subscribe(this) or only subscribe to some specific events whenever they need to and their specific Handle method will be called whenever someone publishes the event. This also allowed us to get rid of the somewhat awkward syntax when testing events (subscription, unsubscription and the actual handing of events) with mocking frameworks.

And as a last bonus, i put a call to the Unsubscribe(IListener) method in the Dispose method of our base Presenter implementation. Which means that none of them will be left subscribed to events by accident anymore :)