How To Refactor And Build Better Microsoft Silverlight Applications

As with all development technologies if you asked two developers how to solve a problem it’s unlikely both would come up with the same solution.

It’s no surprise then the same solution to a problem using Silverlight and WPF applications can be implemented in a number of ways.

In a series of posts I want to show how we can refactor a Silverlight application which “works” to be a lot cleaner, easier to maintain and adheres to good development practices.

Although I’m using Silverlight many of the changes and suggestions would also apply to a WPF application.

So what’s the application?

The application adds two numbers together.

Silverlight Calculator

Yes that’s it. Click here to see a live demo of the calclator.

Using a simple example (as opposed to a huge complex monster) allows us to focus on refactoring and making improvements rather than trying to understand what the application is doing and wading through hundreds of lines of code.

So what’s wrong with it?

The XAML is shown below

    <Grid x:Name="LayoutRoot" Background="White" Height="100" Width="350">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox Grid.Column="0" Text="0" Height="25" TextAlignment="Right" x:Name="tbFirstValue"/>
        <TextBlock Grid.Column="1" Text="+" Height="25" TextAlignment="Center"/>
        <TextBox Grid.Column="2" Text="0" Height="25" TextAlignment="Right" x:Name="tbSecondValue"/>
        <TextBlock Grid.Column="3" Text="=" Height="25" TextAlignment="Center"/>
        <TextBlock Grid.Column="4" Text="0" Height="25" TextAlignment="Left" x:Name="tbResult"/>
        <Button Grid.Row="1" Grid.ColumnSpan="5" Margin="0,5,0,0" Content="Calculate" x:Name="btnCalculate" Click="btnCalculate_Click" />
    </Grid>

and this is what the code behind looks like

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void btnCalculate_Click(object sender, RoutedEventArgs e)
    {                       
        tbResult.Text = (Convert.ToInt32(tbFirstValue.Text)  + Convert.ToInt32(tbSecondValue.Text)).ToString();            
    }
}

As it stands the application:

  • Contains code in the code behind file. OK it’s not so much of an issue for this example and is down to individual preference, but this can quickly become a nightmare to maintain during the life of an application
  • Isn’t unit testable – we can’t test two values can be added together
  • Has no separation of concerns – the code behind shouldn’t be responsible for adding the numbers together
  • A lot of repetition for the styling of the input boxes – if we wanted to make the input boxes bigger we would have to make multiple changes, ideally changes should only need to be made in one place.
  • No validation – if the user enters alphabetical characters into application and hits the calculate button the application crashes

So how are we going to improve it?

By taking an agile approach the aim at the end of each refactoring is to have a releasable application i.e. be able to add two numbers together. Therefore each refactoring will involve small incremental changes.

After each refactoring exercise we will review the application to see what improvements have been made and if any new problems have been introduced…

Comments