Tuesday, June 21, 2011

NGTweet Part 5 : Big Bang Refactoring

 

In the 4th part of NGTweet series I had discussed about plans to introduce new functionality to NGTweet. But I wasn’t feeling great about the way the application was developed. I wasn’t following TDD, the application did not have much separation of concerns, the code looked very spaghetti.I somehow don’t feel comfortable working with spaghetti code.

I decided to refactor the work done so far. Initially I was thinking of introducing one change at a time. But then it would have been boring to add one feature and blog about it. So I have done a big bang refactoring and this post is about the summary of changes done since the last post. While refactoring I did come across some hiccups. I’ll try to highlight them as well.

Refactoring 1 – Unit test service

Easiest thing to start off was to add Unit tests for the TweetSharp service. There is minimal logic in the service as it acts as a wrapper over the TweetSharp library. But still I wanted to make sure that the features that I am going to add, do not break the existing functionality. I also wanted to try my hands at mocking framework called Moq. I have been using RhinoMocks for past 18 months or so. Many people suggest that Moq is easier, elegant and better to use. This was a easier thing to do. Both RhinoMocks and Moq have similar concepts and I am sure it must be same for any dynamic mocking framework available out there. So the first step I did was to unit test the service. These are straightforward tests and I won’t replicate them here. You can check them out in the source code available for download.

Refactoring 2 - Abstract IsolatedStorage into an Interface

The user interface layer had one of the most unstructured code I had written ever. There were direct calls to service, the presentation and business logic was residing in the same file. External dependencies like IsolatedStorage were directly used without being abstracted. Many people would say that using IsolatedStorage directly in code is acceptable as it is part of Silverlight. But I feel a strong urge to provide a level of indirection by abstracting it into an interface.

There are various reasons for doing so. First and the primary reason is it allows us to unit test the application. But that’s not a strong reason. People who don’t follow TDD will argue that there are applications which are using IsolatedStorage and not doing TDD which are running fine in production environment. 

The other reason is to avoid code changes due to changes to the underlying framework. I’ll take an example here. We can use configuration settings by means of Web.config or App.config depending on the type of application. We can programmatically access these settings. This functionality is available since the beginning of DotNet framework. But the way in which these settings are accessed has undergone multiple changes with almost every major release of Dotnet framework. It could be in the form of introduction of ConfigurationManager class or something else liek deprecating some methods. Imagine you are accessing these settings in 100 different files. When the framework changes and you decide to upgrade your codebase you’ll have to change in all those 100 places. Instead if we abstract it to a centralised location, maintenance of such code wouldn’t be a problem at all.

Based on whatever I was doing to work with IsolatedStorage I created an interface called IApplicationSettingsProvider

    public interface IApplicationSettingsProvider

    {

        object this[string key]

        {

            get;

            set;

        }

 

        bool Contains(string key);

    }

Another advantage I have here is I can swap the implementation of IApplicationSettingsProvider. For a Silverlight application I can use IsolatedStorage. But for a WPF application I can use some other storage mechanism like an encrypted XML file or a database or an object database. For an ASP.NET or ASP.NET MVC application I can use build in provider model to store application settings. The possibilities are many because we’ll be programming to an interface instead of a concrete class.

Thais step ensured that one of the infrastructure dependency was nicely abstracted.

Refactoring 3 - Integrate MVVMLight

Since the introduction of NuGet integrating third party dll’s is become a piece of cake. I did it for Moq and this time around for MVVM Light. I am using Moq again in the unit tests related to ViewModel. One thing I did not appreciate from the previous code was that the view had too much  knowledge about the model. It was aware of which service was getting called, what was the internal data structure etc.

Ideally a view should only be concerned about displaying data to the user and handling user actions like selecting of a drop down list or text input or button click etc. But in our case the view was aware that the item source to which the list was bound to had a sub property called User.ScreenName. To me this looks like violation of the basic rule that view should be as dumb as possible.

So to overcome this we introduce our good friend, view model from the Model View ViewModel presentation pattern. So I refactored the main page to have a MainViewModel as its view model. This view model would be responsible for performing the service operations and updating the UI. The individual items in the listbox are also having their own view model which is called TweeterStatusViewModel. I’ll talk about this in much more detail in the future post.

I had a temptation to use the DialogService for showing the message boxes. In fact I did have one and it was working fine. But then I cam across a nice feature in MVVM Light which allows you to create messages in a very decoupled way using the DialogMessage class. There is also a feature called Messenger which acts more like an EventAggregator of Prism. Using Messenger we can publish messages from the view model and subscribe them from other view models or views itself. So I made use of this to display message box instead of taking the dialog service route. I am still not sure what is the best approach. May be as the application grows I’ll get a better picture if I need to provide an abstraction over the Messenger itself. But for time being I’ll not be using the dialog service.

Another thing that needs special attention that needs to be paid while updating the view model properties from the Async calls made to the web service. An exception  is encountered while trying to update properties bound to view on the view model. In SIlverlight the service calls are always made asynchronously. As a result the callback runs on a separate thread. When we try to update view model properties, we get cross thread access exception. To overcome this we can use the Dispatcher class available in Silverlight or WPF.

Once again MVVMLight comes to the rescue. It has a nice little helper called DispatcherHelper to help us run code on the UI thread. For the DispatcherHelper to work we need to initialize it when the application starts. I added a line in the Application_Startup event as follows

        private void Application_Startup(object sender, StartupEventArgs e)

        {

            this.RootVisual = new MainPage();

 

            DispatcherHelper.Initialize();

        }

After the DispatcherHelper is intialized, it can be used from anywhere like

        public bool HasTweets

        {

            get

            {

                return _hasTweets;

            }

 

            set

            {

                if (_hasTweets != value)

                {

                    _hasTweets = value;

 

                    DispatcherHelper.UIDispatcher.BeginInvoke(() => RaisePropertyChanged("HasTweets"));

                }

            }

        }

 

Refactoring 4 – Deploy web application to IIS Server

After I converted the application to view model, the images were not visible in the displayed results. There seems to be a limitation with Silverlight that you cannot access URL’s for images and media if you are running from a file based location which is the default if you are using the built in web server of Visual Studio 2010. You’ll encounter the AG_E_NETWORK_ERROR as shown below

image

The Silverlight Image control raises an ImageFailed event whenever it is unable to bind the image to the image source. We can tap into this event and debug based on the type of the exception. In my case it was a network error. So I changed the project setting to deploy the application to local IIS web server.

image

With this change all the images were displayed as before. Please note that this change of hosting the application in IIS needs to done for the Web application project which is used for hosting the Silverlight application.

Refactoring 5 – Unit Test View Model

To unit test the ViewModel I created a Silverlight Unit Test Application. There was some problem with regards to using a normal test project due to incompatible dll’s. I tried for almost a day before giving up to use a normal unit test project. One disadvantage of using the Silverlight Unit Test application is we don’t get code coverage result. I hope Microsoft will address this issue in their next release. Here is an output of the unit test related to view model run through Silverlight unit testing application.

image

The output isn’t very appealing. But still something is better than nothing. With these changes I have completed a major refactoring. This is how the application looks. There is not much change in the visual appearance but for sure it has become more maintainable Smile

image

Refactoring 6 – Use NBuilder to generate test data

Every time we have a complex object graph, it comes difficult to build these objects while unit testing. One of the basic rule of unit testing is to arrange the inputs. Since each test is meant to test one single unit of execution, it might not require all the objects which are related to the parent object. Also if we are dealing with lists its cumbersome to generate lists by hand. Long time back I had blogged about using an open source tool called NBuilder to generate test data. I have used the same here for some of the tests and I intend to continue using it for the future tests.

Conclusion

Addition of service layer tests and separation of concerns for the UI layer were the main objectives of this refactoring. This gives a good safety net to experiment with the application. Integrating MVVM Light and Moq was much simpler than expected.

I did not find much difference between Moq and Rhino Mocks. The syntax looks cleaner in Moq and there is no concept of Record and Play as with Rhino Mocks. But recent versions of Rhino Mocks support AAA style of mocking which is almost similar to what Moq offers.

There were few bonuses as well that came along with MVVM Light in the form of Messenger and DispatcherHelper. In its current state the UI layer is dependent on ViewModel which interacts with the service layer. There can be few more improvements done down the line. I hope this has provided a good foundation for me to build upon the next set of features.

As always the complete working solution is available for download.

Until next time Happy Programming Smile

Sunday, June 05, 2011

NGTweet Part 4 : Control Templates for better UI

 

This is the 4th part of the NGTweet series. In the previous post I demonstrated how to use Themes to enhance the user experience by building consistent UI. In this post I’ll take another step towards making the UI better from what we have currently for the NGTweet application. So far we have been displaying the tweets in a list box with just text. In most of the social media applications we would get to see the profile image of the person who is associated with a Tweet, a scrap, a poke or whatever jazzy name is given for a user action.

So in this post I’ll make two enhancements to the UI. I’ll add the profile picture of the person who originally twitted and also the date on which it was twitted. In future post I want to highlight the feature called ValueConvertor in Silverlight to add some context to the date to make it more relevant for the user. Also I’ll demonstrate the ability to display additional options with the selected tweet. Another features I have in my to do list are the ability to Tweet, ReTweet, send direct messages(replies), mark tweets as favourites, filter tweets and so on. Lets get started with the profile image and the created date features for this post.

Add ProfileImage and CreatedDate to Service layer

If we go back to the first post of this series, we created a very elementary domain model in our service layer. This had the screen name and the Tweet properties associated with it. It was sufficient for the first getting started example. But with changing requirements we need some changes to the domain model. I have based my model on the similar data structures available in TweetSharp library. So I refactored the NGTweeterStatus class and added NGTweeterUser class. Because of the problem with serialization which I mentioned earlier I had to take these steps. I added the required adapter  for TweeterUser. After these minor changes, the NGTweeterStatus class look like

    [DataContract]

    public class NGTweeterStatus

    {

        [DataMember]

        public string Tweet { get; set; }

 

        [DataMember]

        public NGTweeterUser User { get; set; }

 

        [DataMember]

        public DateTime CreatedDate { get; set; }

    }

I removed the ScreenName property and replaced it with a full fledged User property. This encapsulates the user relate properties into a single object which is represented by NGTweeterUser class. I added the CreatedDate property to store the date of the tweet. And the NGTweeterUser class is as follows

    [DataContract]

    public class NGTweeterUser

    {

        [DataMember]

        public int Id { get; set; }

 

        [DataMember]

        public string ScreenName { get; set; }

 

        [DataMember]

        public string Name { get; set; }

 

        [DataMember]

        public string ProfileImageUrl { get; set; }

    }

I will not display the code for the two adapters here as they are basically mapping properties from one class to another. You can check it out in the downloaded code.

Modify ListBox Control Template

Since the service implementation has changed I had to update the service reference. Because the internal representation of the data was also modified, I need to change the bindings as well. I rectified one of my mistake from the previous posts. I was using TwoWay binding. Actually we don’t need two way binding because I am not going to modify the tweets or any other details. In essence these are readonly properties. So I changed those bindings to OneWay to optimize the performance a little bit. Instead of showing the changes one by one, I’ll show the final markup itself

                    <ListBox.ItemTemplate>
                        <DataTemplate>

                                <Border Margin="2"
                                       Padding="3"
                                       BorderBrush="Black"
                                       CornerRadius="5"
                                       BorderThickness="1">
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto" />
                                            <ColumnDefinition />
                                            <ColumnDefinition />
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition />
                                            <RowDefinition />
                                            <RowDefinition />
                                        </Grid.RowDefinitions>

                                        <Image Source="{Binding User.ProfileImageUrl}"
                                              Height="40"
                                              Width="40"
                                              Margin="5"
                                              Grid.RowSpan="3"
                                              Grid.Row="0"
                                              Grid.Column="0"
                                              HorizontalAlignment="Center"
                                              VerticalAlignment="Top" />

                                        <TextBlock Text="{Binding User.ScreenName, Mode=OneTime}"
                                                  FontWeight="Bold"
                                                  Grid.Row="0"
                                                  Grid.Column="1" />

                                        <TextBlock Text="{Binding CreatedDate, Mode=OneTime, StringFormat='\{0:m\}'}"
                                                  TextAlignment="Right"
                                                  Grid.Row="0"
                                                  Grid.Column="2" />

                                        <TextBlock Text="{Binding Tweet, Mode=OneTime}"
                                                  TextWrapping="Wrap"
                                                  Grid.Row="1"
                                                  Grid.Column="1"
                                                  Grid.ColumnSpan="2"
                                                  Margin="2"/>
                                    </Grid>

                                </Border>
                        </DataTemplate>
                    </ListBox.ItemTemplate
>

I replaced the item template of the listbox. Earlier we had a stackpanel, this time I needed a layout with ability to specify different alignments for different controls. So I chose to use Grid. I placed the Image control to display the profile image on the top left corner. Then the ScreenName of the user followed by the date. The date is Right aligned. And finally the tweet in the second row of the grid spanning multiple columns. The profile image spans multiple rows. With all these changes the final output looks like


NGTweet screenshot


I think it looks pretty good compared to the scaled down text only version from previous post.


The image is displayed using the Image element and settign its source to the ProfileImageUrl property. I have also added markup for displaying the CreatedDate. Another feature I have used here is the formatting for date using StringFormat parameter of the databinding. Lets look closely at that piece of code

<TextBlock Text="{Binding CreatedDate, Mode=OneTime, StringFormat='\{0:m\}'}"
                                                  TextAlignment="Right"
                                                  Grid.Row="0"
                                                  Grid.Column="2"
/>

In previous versions of Silverlight we had to use the ValueConvertor for achieving something similar. But with Silverlight 4, we can use StringFormat which are commonly used formats for the formatting of values. Here I am using the date format which displays the date in month and day of month format.


Conclusion


When I started with this post in mind, I was thinking it might take me couple of hours to implement all these features. But it turned out to be far less than that. With Silverlight Control templates it was very easy to customize the look and feel of the controls. As we saw here that to change from a stack panel based layout to a grid based layout it was very simple. Addition of the StringFormat feature for binding has also made it easier for developers to display data in different formats lot more easier. It saves a lot of boilerplate code which needs to be written otherwise using ValueConvertors. I hope these features were useful to add to this tiny app.


As always the complete working solution is available for download at dropbox.


Until next time Happy Programming Smile

Wednesday, June 01, 2011

NGTweet Part 3 : Use Silverlight Themes to enhance UI

Background

This is the third part of the series in building the Silverlight Twitter client application which I have named NGTweet. You can refer to the earlier post if you had missed it. I did not pay much attention to the user interface in the previous posts. One of the strong point in favour of Silverlight as well as WPF is that we can build rich User Interfaces. The divide between developers and  designers can be reduced by using tools like Expression Blend to build “cool” applications.

For a developer its always difficult to come up with the right mix of colours and textures to give a consistent look and feel. We tend to spend more time getting the logic in place. People with designer skills are good at developing user interfaces which are user friendly and appealing to the end user. Microsoft has released a set of Themes to help developers build consistent and appealing UI. I am going to demonstrate it in this post.

Pre-requisites for using Silverlight Themes

Silverlight has build in support for applying styles and Themes to controls. This has been there since the first edition. But it is always time consuming to handcraft each and every style and theme. With the release of Silverlight toolkit Microsoft published  prebuilt Themes which are very easy to use. We need to install the Silverlight toolkit to get started. There are dedicated versions of the toolkits available for WPF, Silverlight and Windows Phone 7. These are also based on the version of Silverlight or other technologies like Silverlight 4.

For the purpose of this demo I am using the Silverlight 4 toolkit. The toolkit contains additional controls which add to the core framework controls like the Calendar control, Busy Indicator etc. I’ll explore some of these controls in future postings. Assuming that you have the required infrastructure including Visual Studio 2010 and Silverlight 4 toolkit lets continue from where we had left last time around.    

Use Silverlight Themes

When we displayed the results in the list box last time it was displayed with just a border around the items. It wasn’t very appealing and user friendly. So I thought of modifying the plain border into a rounded corner one.

                                <Border Background="BlanchedAlmond"
                                       Margin="2"
                                       Padding="3"
                                       BorderBrush="Black"
                                       CornerRadius="5"
                                       BorderThickness="1"
>

Its a simple change but I like the end result. There is slight discomfort in the look of the text as well, when it stretches beyond the width of the list box and the horizontal scrollbar appears. Also the border doesn’t stretch uniformly for all text.  Turns out that we need to disable the horizontal scrollbar of the ScrollViever control. And to fix the border issue we need to provide the ItemContainerStyle for the listbox item. These two changes are shown below

                <ListBox Name="lstTweets"
                        Width="400"
                        ScrollViewer.VerticalScrollBarVisibility="Auto"
                        ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                        HorizontalContentAlignment="Stretch"
                        Height="500">
                    <ListBox.ItemContainerStyle>
                        <Style TargetType="ListBoxItem">
                            <Setter Property="HorizontalAlignment"
                                   Value="Stretch" />
                            <Setter Property="HorizontalContentAlignment"
                                   Value="Stretch" />
                        </Style>
                    </ListBox.ItemContainerStyle
>

The result of these changes is seen in the screenshot below


image


With the listbox in decent shape, lets turn our attention towards themes. There are 12 default Themes available with the Silverlight 4 toolkit. We can access them from the toolbox.


image


To start using a particular theme we can drag and drop the theme from toolbox onto the designer surface. Based on which theme is selected the reference will be added to the project references.


image


Each theme is a separate dll. I tried different themes so I have got references to all the ones which I tried. Once you have finalized the preferred theme, you can remove the unused references. As can be seen from the screenshots there is also a namespace added to the user control

 xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"

The dll related to this is also added to the references when we drag a theme from toolbox. Once the references are added we can start using the theme for the controls. When we drag a theme it would create a tag in the XAML automatically based on where we drop it. We might need to position it appropriately. In my case I would like to to apply the theme for the complete user control. So I place it as the first content element of the user control itself. So all the controls will get wrapped inside the theme.

<UserControl x:Class="NGTweet.MainPage"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            mc:Ignorable="d"
            d:DesignHeight="300"
            d:DesignWidth="400"
            xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
    <toolkit:ExpressionDarkTheme
>

In the last line we applied the ExpressionDarkTheme to this user control. Similarly we need to have the closing tag before the end of user control markup.

    </toolkit:ExpressionDarkTheme>
</UserControl
>

This will apply the settings from the theme to the controls. Lets take a look at the screen after applying this theme.


image


The background and the look of the scrollbar has changed. But the listbox looks ugly. That's because the background we have specified for the list box item control. The value is overriding the default style provided by the theme. Lets go and remove the background and see if it improves things with the default theme settings.

                                <Border Margin="2"
                                       Padding="3"
                                       BorderBrush="Black"
                                       CornerRadius="5"
                                       BorderThickness="1"
>

image


That change solved our problem. Now the UI looks neat and clean. Just to highlight the difference in appearance I’ll provide screenshots of couple of other themes. Here is the output of applying the BubbleCremeTheme


image


This is BureaBlueTheme in action


image


And the last one I would try is ShinyRedTheme


image


Since I am using only listbox control here the difference might not be so contrasting. But when you have a screen filled with all types of controls you can definitely see the difference after applying the theme.


Conclusion


If I were to get the look and feel of the above screenshots it would have taken few hours if not more. People with experience in designer tools like Expression Blend might still be able to get it done is shorter span of time. But not everyone has the privilege of using tools like Expression Blend. For developers working just with Visual Studio 2010 these themes can be of great help. Even if you are using Expression Blend the themes can act as a good starting point to customize only the controls you are interested in and for others continue using the defaults.


You can check the look and feel of different controls if a theme was applied using this link from Silverlight toolkit samples. Apart from the default themes available with the toolkit, Microsoft also released additional themes named Cosmopolitan, Windows, AccentColor and JetPack. All these can be downloaded using this link. Tim Heuer wrote about these themes in his blog on Jetpack and 3 other themes.


As always I have uploaded the complete working solution to dropbox.


Until next time Happy Programming Smile