Quantcast
Channel: chumchase Wiki & Documentation Rss Feed
Viewing all articles
Browse latest Browse all 6

Updated Wiki: Home

$
0
0
ChumChase: an explanation
A client for FriendFeed written in WPF. The intention of the project is to demonstrate how to build a WPF application using Test-Driven Development. In the application, we use a number of patterns such as Model-View-Presenter, PresentationModel, Inversion of Control, and so on.

Do you have some feedback? Disagree with a design choice? Think there is a better way to do something?
Post a message in the Discussions!

You can follow along with the blog posts chronicling the development of ChumChase here.

NOTE I started converting this over to a new approach, as well as brining in Caliburn. The blog posts do not reflect this yet.

 Christopher Bennage : ChumChase News Feed 
Tuesday, January 13, 2009 |  From Christopher Bennage : ChumChase

ChumChase Table of Contents

I opened up the ChumChase code this evening with the sad realization that my last commits were on November 14th. Ouch. In reading over the code, something jumped out at me immediately. In the code-behind for Shell.xaml, I had a lot of logic that didn't need to be there. It was clumsy and not tested, but at least I had left myself a comment to that effect.

The code handled switching from the default view to the 3D view. If you don't know what I'm talking about, go back and read the older posts. The important part of Shell.xaml looked like this:

<Grid>
<ContentControl x:Name="MainView" />

<Button Content="Toggle View"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Click="ToggleView_Click" />
</Grid>


and the handler for the click (along with a dependent method) looked like this:



private void ToggleView_Click(object sender, RoutedEventArgs e)
{
if (MainView.Content is DefaultFeedView)
{
SetView(new _2Don3DView());
}
else
{
SetView(new DefaultFeedView());
}
}

private void SetView(IFeedView view)
{
MainView.Content = view;
view.RefreshButton.Click += Refresh_Click;
}


Yes, _2Don3DView is not a good name. I'll fix it. Aside from the appalling appellation, this code is not very WPF-ish. What is it doing anyway?



ContentControl is really a place holder. It represents the area in the application's shell where we want to stick the main content. In the handler, we check to see what is currently in the placeholder and we switch it out. Since each view had it's own button for refreshing the feed we needed to wire it up each time we switched the view. (Remember this way is naughty-naughty.) Our views implemented IFeedView so we could access their respective Refresh buttons.


A More Excellent Way



My ApplicationController class should really be responsible for this behavior. In order to make that happen, I created a property on it called CurrentPresenter. This property is the presenter that will back the current view. (A presenter is a class that contains the logic for a portion of the UI, the corresponding view is the visual part used to render that presenter.) Since the data context for Shell.xaml is already set to an instance of ApplicationController (it's named _controller in the code-behind), I was able to changed the markup to look like this:



<Grid>
<ContentControl Content="{Binding CurrentPresenter}" />

<Button Content="Toggle View"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Click="ToggleView_Click" />
</Grid>


and then the event handler to this:



private void ToggleView_Click(object sender, RoutedEventArgs e)
{
_controller.ToggleView();
}


And now, let's examine the tests for the desired behavior. I wanted ToggleView to alternate between an instance of DefaultFeedPresenter and an instance of _2Don3DPresenter. (Bad Christopher, bad!) I did not want ToggleView to create new instances, but to reuse existing ones.



[TestFixture]
public class The_application_controller
{
[SetUp]
public void given_a_context_of()
{
// stuff omitted for brevity //
_controller = new ApplicationController();
}

[Test]
public void raises_change_notification()
{
_controller
.AssertThatAllProperties()
.RaiseChangeNotification();
}

[Test]
public void uses_the_expected_presenter_by_default()
{
Assert.That(_controller.CurrentPresenter, Is.InstanceOfType(typeof(DefaultFeedPresenter)));
}

[Test]
public void toggles_to_the_3D_view_when_the_default_is_current()
{
_controller.ToggleView();
Assert.That(_controller.CurrentPresenter, Is.InstanceOfType(typeof(_2Don3DPresenter)));
}

[Test]
public void toggles_to_the_default_when_the_3D_view_is_current()
{
var default_presenter = _controller.CurrentPresenter;
_controller.CurrentPresenter = new _2Don3DPresenter(_controller);
_controller.ToggleView();

Assert.That(_controller.CurrentPresenter, Is.EqualTo(default_presenter));
}
}


Ooo, hey, what's that first test? That raises notification bit? Oh, that just some cool stuff in Caliburn, you can read more about that here.



I added the following lines to ApplicationController in order to pass these tests:



private readonly IList<IPresenter> _presenters = new List<IPresenter>();
private IPresenter _currentPresenter;

public IPresenter CurrentPresenter
{
get { return _currentPresenter; }
set
{
_currentPresenter = value;
RaisePropertyChanged("CurrentPresenter");
}
}

public void ToggleView()
{
CurrentPresenter = (CurrentPresenter is DefaultFeedPresenter)
? _presenters[1]
: _presenters[0];
}


I initialized _presenters in the constructor for ApplicationController with the instances of the presenters. (I was tempted here to introduce an IoC container, but I didn't. We'll talk more about that later.)



So now, when ToggleView is called, the CurrentPresenter property is updated and change notification is raised, but what happens in the UI? How does it render the presenter instances? Well, given the markup from Shell.xaml we listed above, it doesn't do anything.


I Love DataTemplates So Much, Why Don't I Marry Them?



We need to tell WPF how to render each presenter. We already have user controls that define each view. We can reuse those. I added the following to the Grid containing my ContentControl:



<Grid.Resources>
<DataTemplate DataType="{x:Type Model:DefaultFeedPresenter}">
<Views:DefaultFeedView />
</DataTemplate>
<DataTemplate DataType="{x:Type Model:_2Don3DPresenter}">
<Views:_2Don3DView />
</DataTemplate>
</Grid.Resources>


The DataType property tells WPF that anything bound to an instance of the given type should use the template. Since I placed these in the resources for the grid, it will affect any bindings inside the grid. Each data template simply contains the corresponding user control. I could have inlined the user controls, but I already had tests in place and I believe this makes the markup easier to read.



In making these changes, I did break something. Something that was not being tested... but it's time for bed so I'll leave that for another night.



More to come!

Thursday, November 13, 2008 |  From Christopher Bennage : ChumChase

ChumChase Table of Contents

About 5pm today I was burnt-out from some difficult work on a particular client's project. Our last four projects have all been WPF with an emphasis on UI and UX. Fortunately, most of these were green field project, but the one I was working on today was not.

What made it so difficult is that the application is practically one big xaml file with all of the logic in the accompanying code behind. It's hard to modify the UI when it is so tangled up with the logic.  <sigh />

So at 5pm, I decided to take a break and work on ChumChase a bit.

Hope I'm not embarassing anyone...Here's a quick overview of what I did:

  • I began a basic 2D view that will be the actual default view for the application. The 3D view is cool, but it's a novelty and not much else. The 2D is really simple at the moment.
  • You can toggle between the 2D and 3D views. The underlying presentation model is the same. It doesn't change. The only code associate with the views is the trackball code for the 3D view.
  • I added profile pictures for the user associated with a feed entry.

Chasing Simplicity

Let's review my thinking process for adding the profile pictures.

I assumed that I could get the url for a given user's profile picture from FriendFriend's API. In fact, it is quite simple.

http://friendfeed.com/nickname/picture?size=medium

where nickname is the user you are interested in. You can provide small or large for the size as well. FriendFeed uses the term nickname where everyone else would use username.

The data template for a individual item on the feed looks like this (simplified for the post):

<DataTemplate>
<Border>
<DockPanel>
<Grid DockPanel.Dock="Left">
<!-- this image is where the profile pick will go -->
<Image Width="50"
Height="50"
Margin="2,2,8,8" />
<Image Width="16"
Height="16"
VerticalAlignment="Bottom"
Margin="2"
Source="{Binding Path=ServiceIcon}"
HorizontalAlignment="Right" />
</Grid>

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Path=Title}"
TextWrapping="Wrap"
FontSize="16" />
<TextBlock Grid.Row="1"
Text="{Binding Path=User}" />
</Grid>
</DockPanel>
</Border>
</DataTemplate>

The template is bound to an instance of FeedEntry which represents a single entry in the feed. Notice the binding to User in the bottom TextBlock. That's simply the nickname of the user associate with the entry.


My first thought was to add a new property to FeedEntry called UserProfilePictureUrl and bind it to the Source property on the Image.  This new property would merely inject the value of User into a url and return it. Even though it was simple, something nagged me about this. I felt like it should not be a concern of FeedEntry to provide the url for the profile picture. In addition, I knew that I would need to get the url in other places where FeedEntry was not part of the picture.


In some sense, the translation of a nickname into a profile pic url is standalone. I mean, the concept exists independent of any of the current entities in my model. Because of this, I decided to encapsulate the concept in a value converter.

public class NicknameToProfilePicUrlConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string size = (parameter == null)
? "medium"
: parameter.ToString();

string url = string.Format("http://friendfeed.com/{0}/picture?size={1}",
value,
size);
return url;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

Then in the xaml, I used the converter like this (after adding a reference in the resources):

<Image Width="50"
Height="50"
Source="{Binding Path=User, Converter={StaticResource NicknameToProfilePicUrl}}"
Margin="2,2,8,8" />

Notice that I'm actually binding to the nickname (note to self: I should rename User to Nickname). The converter takes the nickname and returns the url. Converters like this are easy to test as well.


This implementation isn't all that robust, but we'll handle that when the need arises.


So how do you feel about having a value converter that is so specific? I find myself using them more and more. Does it bother you to take this approach?


Off to bed...

Saturday, November 08, 2008 |  From Christopher Bennage : ChumChase

Table of Contents

Since my last post on building ChumChase, I've had a couple of projects that have changed my thinking just a bit about how to architect a WPF application. When I reviewed the code for ChumChase (in order to continue this series) I found it needlessly complicated in more than a few places. So I decided to fix it.

A good portion of what I wrote in the first three posts is still true, but I did make changes in two major areas.

Too Much Focus on Presenters

I have had a habit of naively creating presenter classes for every "screen" within an application. I think this is a consequence of my experiences as a Web developer using MVC. With MVC, you really need a controller to coordinate any action with the the view. Not so with a technology like WPF.

What's sad, is that I've known this intellectually for some time. Posts by Dan Crevier and John Gossman explained patterns like DataModel-View-ViewModel a couple of years back.

If that's the case, what did I change?

First, I created a model that represented what is going to be visualized. This is the "ViewModel" mentioned above, although I tend to use the term "Presentation Model". This view or presentation model often mirrors the actual domain model (or data model) of the application, but it has an entirely different set of concerns.

For example, my company worked on the recently released (to beta) MapDotNet Studio UX. It's an application for designing maps to be rendered with MapDotNet Server. There's a domain model for representing the maps and the various layers of data that might be represented on them (e.g., parks, property parcels, postal codes, etc). In this application, we display a list of maps that can be edited. Underlying the application is a domain model that represents the maps and business of rendering them on a server. However, in presenting this model in the UI we need to do things like: keep track of the currently selected map, know wether or not a map is open for editing, and so on. These are presentation concerns and have no business in the domain model. Thus, we create a presentation model.

In many cases, this presentation model is a wrapper around the domain model and adds the presentation concerns. However, the presentation model might stand alone,similar to data transfer objects. In that case, there would need to be some sort of translation between the domain model and the presentation model. All that is to say that there is more than one way to do it.

In some cases, presenters make a lot more sense that a presentation model. The scenario we frequently encounter is a form or wizard-based UI. Presenters are much better suited for these types of UI's.

Of course, there is no reason why an application might not have presenters and presentation model.

Where do you put stuff?

Partial Screen Shot of ChumChaseI'll reference our work on Studio UX again; a user loads a map up from a server, styles the map, and then saves or publishes the map back to the server. A user might initiate publishing a map from any number of places in the UI: right-clicking on a map in the explorer pane, Ctrl+S when a map is open, and so on. So where should the code that actually publishing the map live? These different portions of the UI might be backed by different presenters, or by a class in the presentation model. How do we handle the save?

The missing link is using the Command pattern.

Of course, the Command pattern is built into WPF. It's all other place and part of the WPF Way. Take a look at ApplicationCommands.Save, it's practically a stub for what I just described.

Even though I live and breathe WPF, I was not bringing these concepts into my solutions.

The act of saving the map can be expressed as a command. It might be class named something like the PublishMapCommand. This hypothetical class PublishMapCommand is a first class member of my presentation model. (I'm simplifying the scenario from what the real app dealt with). It has some prerequisites of course, for example it needs a map to operate on, and it might need access to a repository, but it's not tied to a specific presenter or even to a specific instance of a map. The map is provide by the context (the node I'm clicking on the explorer, or the tab that has focus when I press Ctrl+S). My IoC container can handle injecting the repository. And now, I can bind disparate parts of the UI to the same command.

The command is also highly testable because it so focused, it does just one thing. As a side note, thinking about your domain in terms of Verbs is really useful. I would argue much more useful that the traditional approach of thinking in Nouns. Verbs == Behavior, Nouns == Data.

Summing It Up

My basic approach for the UI is this: first, I am thinking in terms of a presentation model. An important part of this model is the verbs or commands. Secondly, where it makes since I use presenters. If necessary, I'll introduce an application controller (or master presenter) to help orchestrate the entire application. Again, if necessary.

The lesson for myself was this: don't get so caught up in the design, that you lose sight of what works. Keep it clear, keep it simple.

I've already committed the changes for ChumChase that reflect these ideas. There aren't any commands in the model yet, but I did away with the HomeFeedPresenter. Instead, I now have the beginning of a presentation model that models the data I want visualized in the application. Right now, that is merely the home feed.

You can get the latest for ChumChase here. The application actually works now , well the minimum base feature works. You'll be prompted for your user name (or nickname) and your remote key. The remote key is different from your FriendFeed password, and you can find it here (assuming you are logged into FriendFeed.) If you are lazy, you can use the default credentials for the dummy account I set up.

Oh, and I started playing with the new 2D on 3D stuff, that's what the screen shot is, but I'll blog about that later.

Oh yeah, and there are some wicked cool new WPF binding tests via Caliburn in there as well.

More to come...

Wednesday, August 20, 2008 |  From Christopher Bennage : ChumChase

Table of Contents

Application Architecture

I'm going to back up and bit discuss my overall approach to structuring this WPF project. So far the solution consists of four projects:

solution
  • ChumChase is the actual WPF project.
  • FriendFeed is the official .NET api I downloaded from here, and patched so that it would compile. :-)
  • IntegrationTests is for testing the bits of the application that interact with the FriendFeed api.  I separated this out because it is much slower to run than my Specifications tests, and goes beyond the trust boundary of the app.
  • Specifications is the bulk of the unit tests for the project. I'm influenced by the whole BDD approach, and I like to think of my unit tests as executable technical specifications.

Project Structure

projectIn the main project you'll find the following:

  • Presenters - This folder contains the presenter classes. I usually name these classes with the suffix "Presenter, though that's a bit of a hang over from other frameworks (MonoRail, RoR). This directory is where I have the HomePresenter class we've been discussing.
  • Views - These are usually user controls or some derivative thereof. I name them to correspond to their presenter. So you would expect, since we have HomePresenter, to find HomeView.xaml. (Actually, I goofed and the current source has the view named HomeFeedView.xaml).
  • Model - This is the object model that represents the "business problem" I'm trying to solve. In this case it happens to mirror the actual api quite a bit.
  • Repositories - Here I am influenced by Eric Evans' book on Domain-Driven Design. Repositories are classes that allow me to access/persist data in a way that makes sense to my business domain. It's also a place where I can hook in orthogonal concerns such as logging, caching, or security. Repositories differ from the traditional data access layer in that there is an emphasis on the domain model (as opposed to following the semantics of a relation database).
  • Services - These are supporting classes. They are not necessarily part of the business or problem domain. A classic example is an SMTP provider. Classes in your model or presenters might utilize these.
  • Framework - These support the framework of application, but don't have anything to do with the business concern. If we need to create a base class for views, we'd put it here. Currently, I have a class there that is going to assist us with binding to commands. This is code that could likely be pushed out to a reusable library.

Aside from these folders you will also find:

  • App.xaml - This is the starting point for the application. It will kick off our Windsor configuration, and launch the first window for the application. Eventually, we'll include some application-wide resources in the xaml, primarily for styling.
  • Shell.xaml - This is the main window of the application. I call it Shell, because there is very little to its UI. It's content is bound to view of our current presenter. This class might have some logic in it's code-behind if we need to do some things like managing a set of tabs. It also provides the overall layout of the application.
  • ApplicationController - I briefly mentioned this in the last post. Honestly, I've waffled a bit on what to call it. It's responsibility is to coordinate the presenters for the application. For example, if presenter X needs to load presenter Y it passes that request to the application controller. In this, it also handles some statefulness for the overall application. This will become more clear as we begin to work with the class.

What's Not Here Yet

There are several other things that usually appear in my projects. I often end up with a base class for test fixtures, though I think the new Rhino.Mocks features might affect that. However, the big piece that's missing is the folders and files related to organizing the XAML.

It's common for me to have the following:

  • Colors & Brushes - I typically have a  resource dictionary dedicated to defining the colors and brushes used in the application.
  • Default Styles - When I provide a completely custom style for an application, I'll have a resource dictionary that defines all of the default styles for controls. It useful to note that I avoid putting control templates inline in this dictionary.
  • Control Templates folder - In this folder, I will have a file for each control template in the application. I'll usually have a "manifest" resource dictionary where I merge in all of the individual templates. This helps to keep the structure clean in other areas. These are the control templates that are referenced in my default styles dictionary.
  • Data Templates folder - Inside the Views directory, I will have a sub-folder for data templates. Data templates really are views.

What Happens at Runtime?

A synopsis of what happens at runtime, well, what will happen once we've finished:

  • App.xaml starts off.
  • In its constructor, we configure our container, which in this case is Windsor.  The container is told how to resolve resources, such as where do I find the actual implementation of IFriendFeedProxy.
  • Still in the constructor, we then request an instance of IApplicationController, and call StartApplication().  Note that we don't set the StartupUri in the XAML for App.
  • StartApplication() might handle some things like loading up user preferences, but mostly it will initialize and open Shell.xaml.
  • Somewhere around here we'll request the HomePresenter from the container, and inject into the shell.
  • As the user interacts with the application, presenters may be removed and new ones injected (probably into a tab, or new window). The shell's code-behind has the code for actually placing these presenter's views into the layout.
  • The presenter will have use commands as properties that can be bound to in there views. These commands are coordinators of individual activities in the application.

I'm certain that parts of this are confusion, but I believe it will make sense as we continue to build the application. As always, your feedback is welcome.

More to come!


Continue to Part 4.

Sunday, August 17, 2008 |  From Christopher Bennage : ChumChase

Table of Contents

So let's get back to this whole building a WPF application thing.

A number of things went down since my last post: I was out sick with a stomach bug for few days, my infant son caught the same bug and subsequently we spent a few days in the hospital (he's fine now, it was nothing serious), and I finally caught up on the AAA syntax in Rhino.Mocks.

Changing My Testing Style

Lots of people have blogged about the AAA syntax here, here, and here (to list a few). I won't go in depth, but briefly the idea is that you arrange your unit test thusly:

  • Arrange: do the minimal setup required to execute the test
  • Act: execute the actual code under test
  • Assert: assert that the code did what you expected

I decided to adopt this style. It seems to yield more readable, more focused, and less brittle tests. I rewrote the test from my last post using AAA.  The original test was this:

[TestFixture]
public class The_presenter_for_the_home_feed : TestFixtureBase
{
private HomePresenter _presenter;
private IFeedRepository _feedRepository;

protected override void given_the_context_of()
{
_feedRepository = Mocks.StrictMock<IFeedRepository>();
_presenter = new HomePresenter(_feedRepository);
}

[Test]
public void can_refresh_the_home_feed()
{
using (Record)
{
Expect.Call(_feedRepository.FetchHomeFeed())
.Return(new List<Entry>());
}

using (Playback)
{
_presenter.RefreshHomeFeed();
}
}
}

and I rewrote it as this:

[TestFixture]
public class The_presenter_for_the_home_feed : TestFixtureBase
{
private HomePresenter _presenter;
private IFeedRepository _feedRepository;

protected override void given_the_context_of()
{
_feedRepository = MockRepository.GenerateStub<IFeedRepository>();
_presenter = new HomePresenter(_feedRepository);
}

[Test]
public void can_refresh_the_home_feed_when_credentials_are_available()
{
_presenter.RefreshHomeFeed();
_feedRepository.AssertWasCalled(x => x.FetchHomeFeed());
}
}

Again, you can gather more details about this approach in one of the links above.


One interesting note though is that AssertWasCalled is an extension method and we're using it to assert the method FetchHomeFeed() was actually called on feedRepository.


(I also think that I should not have used StrickMock in the original test, as that added to fragility of the test.)


I tend to think of my code in terms of sentences and paragraphs, at least when it comes to the use of white space. You'll notice as the tests get a little larger that there will usually be three "paragraphs" in the code: arrange, act, assert.

Focusing on the Story


I said in my last post that the core story for this application is to retrieve the home feed. As such, I'd like to take the shortest path to getting that feature fully functional.  The next few steps are roughly:


  • Write a proxy to wrap the existing FriendFeed api, but just enough to fetch the home feed.
  • Write a repository that will manage the home feed data. Even though this seems superfluous at the moment, it's a seam in the application where I will add future functionality (such as caching, logging, etc.).
  • Provide support for authentication.  The FriendFeed api requires a username and remote key for accessing the home feed.

Very soon, I want to be able to launch the application, click a Refresh button, and see my feed. If I haven't provided credentials, I want the application to prompt me for them.

The Credentials Problem


The parts of the story regarding credentials raise some interesting design questions. Let's consider some of the pieces of the puzzle.


The HomePresenter is going to initiate the act getting the home feed. We've already seen that HomePresenter is going to invoke some implementation of IFeedRepository. The repository will talk to the FriendFeed api through a wrapper (IFriendFeedProxy) . Inside the wrapper class is the official .NET FriendFeed client, and it is the class that is really interested in the credentials. It's what talks to the FriendFeed web service, and that needs to be authenticated with the credentials. So at the bottom of this, somewhere in our code, we'll have this:

FriendFeedClient client = new FriendFeedClient("username", "remoteKey");

classesI'm using the Dependency Inversion Principle (which I'll talk about more later). However a consequence of this is that the constructor for HomePresenter takes an IFeedRepository and an IApplicationController.


In turn, my implementation of IFeedRepository, cleverly named FeedRepository, requires an instance of IFriendProxy in its constructor. My implementation of IFriendProxy wraps the official api. Did you follow all of that?


When I first began working through the design, I thought that I'd have to request the credentials from the user at the presenter level, and then pass them down to the repository, then to the proxy which would in turn set them on the actual client. But I could tell quickly that this smelled bad. The repository doesn't need to be concerned with credentials, and neither the HomePresenter. So far there are really just two classes that need to know about credentials: some sort of UI for getting the credentials from the user (that is a presenter of some sort) and FriendFeedProxy.


Oh and what's this IApplicationController interface all about? Um, I'll come back to that in the next post.

Single Source


Ideally, what I want is a single source for the credentials: a class whose sole responsibility is managing the current set of credentials. This lead me to create an ICredentialsSource interface. In order to flesh out what the interface should look like I began writing tests for how the client proxy would interact with it:

[TestFixture]
public class The_client_for_FriendFeed
{
private const string _username = "your_username";
private const string _remotekey = "your_remotekey";
private ICredentialsSource _credentials;
private FriendFeedProxy _client;

[SetUp]
public void given_the_context_of()
{
_credentials = MockRepository.GenerateStub<ICredentialsSource>();
_client = new FriendFeedProxy(_credentials);
}

[Test]
public void can_get_the_home_feed_when_authenticated()
{
_credentials.Stub(x => x.UserName).Return(_username);
_credentials.Stub(x => x.RemoteKey).Return(_remotekey);
_credentials.Raise(x => x.CredentialsChanged += null, _credentials, EventArgs.Empty);

var feed = _client.FetchHomeFeed();

IList<Entry> entries = feed.ToList();
Assert.That(entries[0].Id, Is.Not.Null);
Assert.That(entries[0].Title, Is.Not.Null);
Assert.That(entries[0].Published, Is.Not.Null);
}

[Test]
[ExpectedException(typeof (WebException))]
public void cannot_get_the_home_feed_when_not_authenticated()
{
var feed = _client.FetchHomeFeed();
}

[Test]
public void updates_credentials_when_the_credentials_source_changes()
{
//arrange
_credentials.Stub(x => x.UserName).Return(_username);
_credentials.Stub(x => x.RemoteKey).Return(_remotekey);

//act
Assert.That(_client.DoesClientHaveCredentials, Is.False);
_credentials.Raise(x => x.CredentialsChanged += null, _credentials, EventArgs.Empty);

//assert
Assert.That(_client.DoesClientHaveCredentials, Is.True);
}
}

These tests live in my IntegrationTests assembly, separate from my "real" unit test is the Specifications assembly. I consider these tests to be integration tests because they actually interact with the web services. They are not run as often as my Specifications.


I found these tests hard to write, and I would appreciate any feedback on how to improve them.


My point here though is to illustrate how these tests led me to create ICredentialsSource. I know that there will be a little more to it, a method perhaps that will allow me to set the credentials, but we'll get to that when we need it.


Right now, the interface looks like this:

public interface ICredentialsSource
{
string UserName { get; }
string RemoteKey { get; }
event EventHandler CredentialsChanged;
}

I obviously need the username and remote key (and I was tempted to create a class that represented them as a unit.) I also discovered that I wanted the credentials source to raise a change notification event so that the proxy client would be aware when the user changed them.


Some other places in the application will actually set the credentials on this source, perhaps a yet-unwritten presenter whose job will be to request them from the user. This really helps to decouple responsibilities and keep the code clean. For this approach to work however, our application will need a single instance of this class. I'll show how I'll handle that when we cover dependency injection.

Next


I had a lot of interruptions trying to complete this post, and I had to go back reread what I've written so far. In doing so, I realized that I ought to take a step back and explain my overall default architecture that I'm using. That will be the subject of my next post; and I promise to get the actual WPF bits soon!


On to Part 3.

Wednesday, July 23, 2008 |  From Christopher Bennage : ChumChase

Table of Contents

I actually meant to say in my last post that I had investigated the API options for FriendFeed and they have a C# wrapper already available here. It's packaged up in a single download with its Python and PHP counterparts.  Unfortunately, it has compilation errors. I fixed the errors and then I let ReSharper (R#) have its way with it [R#: Ctrl+Alt+Shift+F]. Yes, I do understand that the Code Cleanup feature of R# can be a nuclear bomb of churn for diffing your source, but egads I do love it so.

FriendFeed project in the solution explorerI also broke out the FriendFeed classes into separate files [R#: F6].

Hmm, I just decided that I'll notate R# and VisualStudio keyboard shortcuts like this [app:shortcut]. Is there already a convention for that out there?

I also decided to keep the FriendFeed code in a separate assembly. I don't always advocate assembly proliferation, but it made sense in this case. I created a project called FriendFeed and moved all their classes there.  I also preserved their namespace, FriendFeed, as well. (I'm getting tired of typing "FriendFeed".)

At this point, I just wanted to get a feel for the API. So I read over what appeared to be the significant classes, and I used a couple of tests to see how it really works. Simple enough, instantiate the client and call FetchHomeFeed().

Building in Seams

I picked up the term seam from Ayende in this post. You can think of a seam as a natural boundary in an application. It's a place where you easily extend or modify an application. It's a little bit like a Bounded Context, but just a little. I used to try to coerce my design into the metaphor of layers, but seams are a more natural concept. You might also think of them as a way of describing componentized architecture.

Consider the example of a desktop computer: you have a motherboard, CPU, memory, video card, etc. All of the components are required for the computer to function, but you can replace any one of them. You can extend the functionality of the computer by adding more hardware. Some things might be tightly coupled, like those wretched integrated video cards. But you don't think of these components as layers. This is a flexible way to architect your application.

Seams are a standard consideration for me when it comes to designing an application. Yes, you can go crazy with it, you can go crazy with anything. In the case of ChumChase, I don't want to be tightly coupled to the official API. I have a few reasons right now: [a] the official API might change. [b] I might want to implement my own API against their web services just for kicks [c] it's a good excuse to demonstrate the technique. I'm going to hide the FriendFeed API behind a repository. The IFeedRepository interface will be a seam in my application.

MVP

I mentioned before that I'm going to use Model-View-Presenter. This pattern is similar to MVC, and like barbeque sauce, everyone has their own flavor. In my case, a presenter is a class that represents the behavior of the UI, and possibly some state. It is ignorant of how the UI visually appears. The view will be a user control, window, page, tab item, etc. We'll use data binding to glue the two together. The ignorance of the presenter about the view is important because it helps us to isolate the presenter in our unit tests.

TDD

It's sometimes hard to decide where to start writing to tests. I tend to write tests that reflect the behaviors of the user interacting with the application. This is as opposed to testing how the application might interact with a data source, or some other more internal function of the application. This approach of working from the outside in helps prevent me from making too many assumptions about the internals.  The negative is that I have to provide mocks or stubs for the dependencies that I haven't written yet.

My core story, that is the basic behavior that I'm interested in, is for the application to fetch my home feed. I'll place this feature on a class called HomePresenter. HomePresenter might end up being my only presenter, I don't know yet. It common though for applications to have several presenters. We'll talk later about how to logically organize presenters.

Let's look at a test:

[TestFixture]
public class The_presenter_for_the_home_feed : TestFixtureBase
{
private HomePresenter _presenter;
private IFeedRepository _feedRepository;

protected override void given_the_context_of()
{
_feedRepository = Mocks.StrictMock<IFeedRepository>();
_presenter = new HomePresenter(_feedRepository);
}

[Test]
public void can_refresh_the_home_feed()
{
using (Record)
{
Expect.Call(_feedRepository.FetchHomeFeed())
.Return(new List<Entry>());
}

using (Playback)
{
_presenter.RefreshHomeFeed();
}
}
}

First, my TestFixtureBase is just an abstract class to reduce clutter. The Mocks, Record, and Playback properties all exist on it and they are really just pass-throughs to Rhino.Mocks. Likewise, I have a setup method in TestFixtureBase that calls given_the_context_of() before each test is executed. It's meant to reset the system-under-test (SUT) into a consistent and pristine state.


Notice that I named my class and method such that they read as a specification for the behavior I'm testing: The presenter for the home feed can refresh the home feed. I'm not sure that I like saying "presenter" in the specification. If I was working with non-technical users, that wouldn't make sense to them. I could replace it with "UI" or "interface" or "screen" perhaps.


The test has two blocks or phases: record and playback. This is generally a big stumbling block for people. I know when I first encountered it I was thoroughly confused. The record phase is where I tell the test what I'm expecting to happen during the playback phase.  The record phase plays the same roles as asserts.


The function we are really testing here is:


_presenter.RefreshHomeFeed();


Since there is not a state that I can verify after calling RefreshHomeFeed(), I am checking to make sure that it's doing what I expect it to do. That is, I expect it to get a list of entries from a repository of feeds.


The Expect.Call().Return() is Rhino.Mocks syntax that allows me to say: I expect my SUT to execute _feedRepository.FetchHomeFeed() and I expect that to return a List<Entry> instance. Right now Entry is just an empty class, but conceptually it represents a single item in the feed. You should also note that the relationship between my presenter and the repository is established in given_the_context_of().


Yes, this is a simple test, but writing this test helped me to shake out what I needed.  Unfortunately, the test as it stands here does not reflect the process of writing it.  I wrote some things, decided they didn't look right, changed them a bit and so on. It probably took me 10 minutes or so before I settled on what you see.


Moving on to the next test. This is in the same class, so you can read it as: The presenter for the home feed notifies the UI when the home feed is refreshed.

[Test]
public void notifies_the_UI_when_the_home_feed_is_refreshed()
{
var property_has_changed = false;

_presenter.PropertyChanged +=
(s, e) => { property_has_changed = (e.PropertyName == "HomeFeed"); };

_presenter.RefreshHomeFeed();

Assert.That(property_has_changed);
}

I want to verify that when I call _presenter.RefreshHomeFeed() a change notification is raised for the HomeFeed property. This means my presenter needs a HomeFeed property. I have a boolean flag that helps me track the state and I'm using an inline delegate to set my flag when the property is changed. (There's actually a flaw in this test that we'll examine later, can you see it?) 


I don't like strings though. If I happen to change the name of the HomeFeed property and forget to change the string in the test, I've broken my test. Of course, I'll notice as soon as I run the tests, but it would sure be nice to eliminate the string. So I wrote this extension method for PropertyChangedEventArgs:

public static bool HasChanged<T>(this PropertyChangedEventArgs args, Expression<Func<T>> property)
{
var expression = (MemberExpression)property.Body;
return expression.Member.Name == args.PropertyName;
}

Now I can change my test to the following and eliminate the string:

[Test]
public void notifies_the_UI_when_the_home_feed_is_refreshed()
{
var property_has_changed = false;

_presenter.PropertyChanged +=
(s, e) => { property_has_changed = e.HasChanged(() => _presenter.HomeFeed); };

_presenter.RefreshHomeFeed();

Assert.That(property_has_changed);
}

Of course, in between these tests I was writing code to make them pass. (Red -> Green -> Refactor, right?) Here's what my presenter class looked liked afterwards:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using ChumChase.Extensions;

namespace ChumChase.Presenters
{
public class HomePresenter : INotifyPropertyChanged
{
private readonly IFeedRepository _feedRepository;
private IList<Entry> _homeFeed;

public HomePresenter(IFeedRepository feedRepository)
{
_feedRepository = feedRepository;
}

public IList<Entry> HomeFeed
{
get { return _homeFeed; }
private set
{
_homeFeed = value;
OnPropertyChanged( ()=> HomeFeed);
}
}

public void RefreshHomeFeed()
{
HomeFeed = _feedRepository.FetchHomeFeed();
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged<T>(Expression<Func<T>> property)
{
if (PropertyChanged != null) PropertyChanged(this, property.CreateChangeEventArgs());
}
}
}

The source is now available here. More to come!


Continue to Part 2.

Monday, July 21, 2008 |  From Christopher Bennage : ChumChase

Table of Contents

In a rather indirect way, I was inspired by a commenter on one of Scott Hanselman's posts to begin a series that walks through building a WPF application from start to finish. We did this for four different applications in our book, but those where targeted to demonstrate particular facets of WPF whereas in these (yet unwritten) posts I'd like to focus more on "this is how I build my WPF apps". Not to say that my way is the *right way*, but so that we might learn together. In the spirit of the aforementioned post, I'm bound to make mistakes, so please (gently) correct me when you think you see one.

What to build?

You might not have noticed, but there's quite a bit of .NET chatter in twit-space. There are already lots of Twitter clients, and some are WPF, so that path has been rigorously trod. However, the technical difficulties surrounding Twitter has given rise to the popularity of another mash up web 2.0 thingy app called FriendFeed.  Everyone seems to agree that the web interface for FriendFeed is all stinky bad, and there's an API readily available, so I think a FriendFeed client is in order.

ff_logo Briefly, FriendFeed is a way to consolidate all of your creepy Internet voyeurism in one spot. You can track a friend's Flickr account, NetFlix queue, Amazon wishlist, and yes, their Twitter tweets and much, much more. Oh yeah, and you can subscribe to me here. (I'm such a loser.)

What to do?

I'm not going to set an agenda or outline a detailed plan. I'm just going to post as I have time to work on it. I started tonight, so I'm expecting to have a real Part 1 posted by midweek. I've already set up a project at CodePlex (though it won't be published for a few more days still.) I named it ChumChase. Isn't that great?

Part of my plan is to step you through my thinking and decision making process in sort of Nilssonian way. I've only just begun but here's what I can tell you so far.

  • I'm going to use a Model-View-Presenter pattern
  • Expect to see some DDD artifacts.
  • I'm going to use NUnit and RhinoMocks.
  • I'll probably use Windsor too (or maybe StructureMap though, anybody have a preference?)

I had intended to write a set of user stories  using the issue tracker of CodePlex. However, I got tired of retyping them every time the site errorred out, which was about 60% of the time. (Is that typical for the CodePlex issue tracker? This was my first usage.)  It also occurred to me that I am lazy and ought to have a life outside of coding, so sorry no user stories.

What to think?

I'm all about conversation. If this interests you, please let me know. I welcome (friendly) criticisms as well. The more I hear, the more motivated I'll be to do it. (Believe me there's a lot to distract right now. I had a new baby son born on the 10th.)


Continue to Part 1

 Christopher Bennage : ChumChase News Feed 



Viewing all articles
Browse latest Browse all 6

Latest Images

Trending Articles





Latest Images