// Arrange Act Assert

Jag Reehal on Agile Development, ASP.NET MVC, Silverlight and all manner of good stuff


How to Apply the Single Responsibility Principle to View Models in Silverlight and WPF

Posted on | June 14, 2010 | No Comments

When you’re using the MVVM pattern with WPF or Silverlight it’s very easy to a have ViewModels that do too much.

In this part of the Silverlight Refactoring series we will convert a ViewModel with multiple responsibilities so that it adheres to the Single Responsibility Principle (SRP).

The code used in this post can be downloaded here.

Why should you care?

Currently the ViewModel looks like this

using System;
using System.ComponentModel;
using System.Windows.Input;

namespace SilverlightCalculator
{
    public class CalculatorViewModel : INotifyPropertyChanged
    {
        private string _firstValue;
        private string _secondValue;
        private string _result;

        private readonly ICommand _calculateCommand;       

        public event PropertyChangedEventHandler PropertyChanged;

        public CalculatorViewModel()
        {
            _calculateCommand = new RelayCommand(Calculate){IsEnabled = true};
        }

        public void Calculate()
        {
            Result = (Convert.ToInt32(FirstValue) + Convert.ToInt32(SecondValue)).ToString();
        }

        public string FirstValue
        {
            get { return _firstValue; }
            set
            {
                _firstValue = value;
                OnPropertyChanged("FirstValue");
            }
        }

        public string SecondValue
        {
            get { return _secondValue; }
            set
            {
                _secondValue = value;
                OnPropertyChanged("SecondValue");
            }
        }

        public string Result
        {
            get { return _result; }
            private set
            {
                _result = value;
                OnPropertyChanged("Result");
            }
        }

        public ICommand CalculateCommand
        {
            get { return _calculateCommand; }
        }

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this,
                    new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

As you can see the logic to add two numbers is in the Calculate method of the ViewModel.

Therefore the ViewModel is responsible for calculating two numbers.

A ViewModel without separation of concerns is difficult to test, maintain and contains code you can’t reuse.

Although we’re only adding two numbers here, brushing the issue under the carpet will have consequences later down the line.

For example in addition to adding numbers what if another developer was given the task of storing the result in a database.

If the ViewModel was as it is now, with no separation of concerns, there is a chance they would put the code to store the value in the calculate method like this

public void Calculate()
{
    // Calculate result
    Result = (Convert.ToInt32(FirstValue) + Convert.ToInt32(SecondValue)).ToString();

    // Store value in database
    DatabaseConnection connection = new DatabaseConnection();
    DatabaseCommand command = new DatabaseCommand("TSQL TO STORE RESULT", connection);
    command.ExecuteNonQuery();
}

Now the ViewModel would be responsible for two things. Next it would be three and this would continue until someone decides to separate the concerns or it gets to a stage where it’s impossible to work with let alone read.

Refactoring the ViewModel to follow the single responsibility principle

Let’s start by creating a class for calculating numbers.

public class Calculator
{
    public int Add(int firstValue, int secondValue)
    {
        return firstValue + secondValue;
    }
}

Notice how the parameters passed to the method are integers, the calculator doesn’t accept string values.

What we are saying here is while it’s acceptable for the ViewModel to use strings for storing numbers the domain layer (or business logic if you prefer) does not.

In other words the add method does nothing more than add two numbers together. Validation should be handled elsewhere.

This makes the unit tests for the calculator very easy to write

[TestFixture]
public class When_calculating_numbers
{
    [Test]
    public void Should_be_able_to_add_two_numbers_together()
    {
        // Arrange
        Calculator calculator = new Calculator(); 

        // Act
        var result = calculator.Add(5, 5);

        //Assert
        Assert.That(result, Is.EqualTo(10));
    }
}

The code below shows how the ViewModel could create an instance of the Calculator class and call the Add Method. Notice how I say could and not should. We’ll see why later in the series.

public void Calculate()
{
    Calculator calculator = new Calculator();
    Result = calculator.Add(Convert.ToInt32(FirstValue), Convert.ToInt32(SecondValue)).ToString();
}

So what have we achieved?

As good boy scouts we have ‘left the ViewModel cleaner than we found it’.

By following the single responsibility principle we have created a ViewModel which is a better canvas for other developers to work with.

If you have arrived here from a search engine, this post is part of series about refactoring Silverlight applications. So if you’re thinking why is the calculator class tightly coupled to the ViewModel? Find out how this can be resolved by applying SOLID design principles using MEF in Silverlight and WPF.

Comments

Leave a Reply