Aug 1 2010

Test-Driven Development Videos – Now on YouTube!

Category: Matt @ 23:41

I uploaded my Test-Driven Development videos to YouTube.  You can check them out here.  Unfortunately I had to manually recapture the video from ScreenToaster, so the audio and video quality took a hit.  However, unlike ScreenToaster, YouTube will allow you to skip around.  In the future, I’ll be sure to capture screencasts in a format that won’t require me to re-rip things.

Tags:

Jul 28 2010

Test-Driven Development – From Painful to (Near) Zero Friction

Category: .NET | TestingMatt @ 14:26

I don’t like development friction.  I especially don’t like testing friction.   Over the last several years, my approach to test-driven development and the style of test cases I create has changed drastically in an effort to eliminate testing frication.  To illustrate, I’ve created my first ever screencasts.  In these screencasts, I use TDD to implement a class in RageFeed.  Starting with very coarse, high-friction unit tests, I’ll show you how you can gradually reduce the friction by creating better tests.  Finally, I’ll show you how easy it is to create clean, readable, specification-style tests in RageFeed today.

Note: I apologize for the limitations of ScreenToaster’s player.  I’m in the process of mirroring the videos elsewhere, and I’ll update the post with links as soon as I get around to doing that.

In these screencasts, you’ll see me use a variety of tools.  They are:

Test-Driven Development - Part 1 (View)

In part 1, I introduce the class I’m going to be implementing, and I use TDD to flesh out the class.  I intentionally create my tests as I would have several years ago (meaning they suck).  From there, I gradually evolve them into a better suite of tests, but there’s still room for improvement.

Test-Drivent Development - Part 2 (View)

In part 2, I leverage some ReSharper templates and some base classes I’ve created in RageFeed to create replace my tests with behavior-driven development style specifications.  The result is (near) zero friction testing.

Downloads

I’ve packaged up the base SpecsFor<T> class as well as my ReSharper templates.  Feel free to use them for whatever you like! 

Download SpecsFor and ReSharper Templates: download

Questions? Comments?

I’m certainly not claiming that what we have in RageFeed is The One Way to do testing in .NET.  It works well for me, but I’d love to hear what others think.  Also, this is my first ever screencast, so please drop me a line and let me know what you liked, what you didn’t like, and what you’d like to see in future screencasts (assuming I actually do more).

Tags:

Jul 25 2010

Starting smtp4dev Automatically

Category: MVCMatt @ 06:35

smtp4dev is a great little tool for testing E-mail sending functionality in your application.  Instead of setting up your own SMTP server and fighting your ISPs restrictions, smtp4dev sits in your system tray and acts like a mock SMTP server, catching instead of relying them on to their destination.  You can then view the messages in the E-mail client of your choice.  Unfortunately, developers have to remember to run smtp4dev before they start testing the application.  If you are building an ASP.NET application, here’s a little trick that you can use to start smtp4dev when your application starts up.  NOTE: Big thanks to Rob for suggesting this.

RageFeed has the following folder structure:

Assets
Databases
Libraries
Source
	...
	Web (our MVC application)
	...
Utilities
	smtp4dev.exe

When a developer launches the ASP.NET MVC application, we’d like for smtp4dev to be launched automatically (if it isn’t already running).  Initially I was trying to make this problem harder than it was, exploring ways to perhaps have Visual Studio launch the process, but Rob’s suggestion was to just throw it in in the Application_Start event: 

protected void Application_Start()
{
    ...

    if (ConfigurationManager.AppSettings["Environment"] == "Development")
    {
        try
        {
            Smtp4Dev.Start();
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException("Unable to start Smtp4Dev, check that AppSettings.Environment is set correctly.", ex);
        }
    }
}

This works, but you have to ensure that smtp4dev will only be launched when developers are testing things locally.  I added an AppSetting that contains the current deployment’s environment (ie: Development, Staging, Production, etc).  The app only attempts to run smtp4dev if the current environment is “Development”. 

The actual smpt4dev bootstrapper is quite simple:

public static class Smtp4Dev
{
    public static void Start()
    {
        if (Smtp4DevIsRunning())
        {
            return;
        }

        var path = HttpContext.Current.Server.MapPath("~/") + @"..\..\Utilities\smtp4dev.exe";

        Process.Start(path, "");
    }

    private static bool Smtp4DevIsRunning()
    {
        return Process.GetProcessesByName("smtp4dev.exe").Length > 0;
    }
}

Presto, when the application starts, it will launch smpt4dev if it isn’t already running.

Tags:

Jul 8 2010

Using MVCContrib glue to bring Visual Basic WebForms and C# MVC together

Category: ASP.NET | MVCMatt @ 16:14

While I’m digging my new job, I’ve found myself in the less-than-desirable situation of having to work with WebForms again.  After working almost exclusively with ASP.NET MVC for the better part of three years, the inadequacies of WebForms seem even more prominent.  While running MVC and WebForms in the same applications is easy enough, we’re facing an added complication: our WebForms application was written in Visual Basic.  While you can’t mix-and-match C# MVC and VB WebForms within the same application directly, you can leverage MVCContrib’s Portable Areas to bring the two together, which is what I’ll show you how to do in this post.

Giving credit where credit is due, Jeffery Palermo already described how you can leverage MVCContrib’s Portable Areas within a WebForms application.  Unfortunately, his sample doesn’t work (it appears to depend on an older MVC 2 CTP), and his post omits several important details.  Jeffery’s post also focuses on the creation of reusable modules whereas my interest is bringing C# into our VB project as seamlessly as possible.  Hopefully this guide, even though it’s focus is on bridging the C#-VB divide, will be useful to anyone that’s envious of MVC but stuck with a substantial amount of WebForms code.

Create a new solution

To get started, let’s go ahead and create a new empty solution in Visual Studio 2010.

VisualStudioNewProject

Next, add a Visual Basic WebForms application.  When you run the application, you should see something like this:

VbWebFormsHome

Note that I modified my master page to make it clear that the master page is a WebForms master page.  You’ll understand why later. 

Add MVC Support

As I mentioned, there’s plenty of information on the web about adding MVC support to an existing WebForms application.  The two play nicely side-by-side in the same project.  First, add references to the required assemblies: System.Web.Mvc, System.Web.Routing, and System.Web.Abstractions.  The last one is probably not strictly required, but I added it anyway. This is also a good time to go ahead and add a reference to MVCContrib.  Note that for the approach I’m going to describe to work, you will need to use a build based on the trunk and not the older release build available from CodePlex.  You can pick up a nightly build from the MVCContrib TeamCity build server (be sure to grab artifacts from a successful build).

MvcContribTeamCity

Next, you need to update your web.config file.  Replace the default compilation section with the following:

<compilation debug="true" targetFramework="4.0">
    <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, 
             Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Routing, Version=4.0.0.0, 
             Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Mvc, Version=2.0.0.0, 
             Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    </assemblies>
</compilation>

Also add a pages element with the namespaces shown:

<pages>
    <namespaces>
        <add namespace="System.Web.Mvc"/>
        <add namespace="System.Web.Mvc.Ajax"/>
        <add namespace="System.Web.Mvc.Html"/>
        <add namespace="System.Web.Routing"/>
    </namespaces>
</pages>

This step probably isn’t necessary (depends on how you are deploying your application), but for good measure, go ahead and add the MVC HTTP handler and a binding redirect for MVC 1:

<httpHandlers>
    <add verb="*" path="*.mvc" 
        validate="false" type="System.Web.Mvc.MvcHttpHandler,
        System.Web.Mvc, Version=2.0.0.0, Culture=neutral, 
        PublicKeyToken=31BF3856AD364E35"/>
</httpHandlers>
<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
        </dependentAssembly>
    </assemblyBinding>
</runtime>

Next up, we need to add some code in our Global.asax file:

Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}")

    ' MapRoute takes the following parameters, in order:
    ' (1) Route name
    ' (2) URL with parameters
    ' (3) Parameter defaults
    routes.MapRoute( _
     "Default", _
     "{controller}/{action}/{id}", _
     New With {.controller = "Home", .action = "Index", .id = UrlParameter.Optional} _
    )

End Sub

Sub Application_Start()
    AreaRegistration.RegisterAllAreas()

    PortableAreaRegistration.RegisterEmbeddedViewEngine()

    RegisterRoutes(RouteTable.Routes)
End Sub

The RegisterRoutes procedure is pretty standard, and AreaRegistration.RegisterAllAreas is boiler-plate MVC 2.0 stuff.  The other bit is important though: PortableAreaRegistration.RegisterEmbeddedViewEngine will register a special view engine that allows the application to consume Portable Areas.

The final thing we need to do is add some special folders that are needed by MVC: the Areas folder and the Views folder.  For now, go ahead and add a view master page at ‘~/Views/Shared/Site.master’.  I’d recommend copying both the Views and Areas folders from an existing ASP.NET MVC application (be sure to remove any of the views you don’t need, but save the Site.master one).  Once you’re finished, you should have a structure like this:

VbProjectCurrentState

At this point, the WebForms project is ready to consume our C# ASP.NET MVC Portable Area.  All we need to do is create one!

Creating a Portable Area

Most people recommend that you create a regular class library to serve as the host of your portable area, but there are some disadvantages to that approach.  First, you will have to re-add all the necessary MVC references in order to build controllers and views.  Second, you will lose all the Visual Studio tooling for MVC (as well as Resharper extensions for MVC projects).  In light of that, I recommend adding a regular-old ASP.NET MVC 2 (C#) application to your solution.  An MVC project is essentially a web application project, which means it produces a single DLL that you can reference from another application. 

After adding your MVC 2 project, you can remove all of the following: web.config files, Global.asax, views (but leave ‘~/Views/Shared/Site.master’ for now), controllers, models, script files, and CSS files. Save your project at this point, then unload it so that you can edit it. 

Edit project file, and add the following line to end of script before closing ‘project’ tag:

<Target Name="BeforeBuild">
  <ItemGroup>
    <EmbeddedResource Include="**\*.aspx;**\*.ascx;**\*.gif;**\*.css;**\*.js;**\*.png;**\*.jpg" />
  </ItemGroup>
</Target>

One of the requirements for building a Portable Area is that the views and any resources they depend on must be embedded in the assembly.  You can do this manually using the Properties pane in Visual Studio, but it’s easy to forget this critical step.  The MSBuild snippet above automatically embeds your views and any common content files. 

With your project file now modified, go ahead and reload it, then add a reference to MVCContrib.  We’ll add a “HelloWorld” controller to our project:

public class HelloWorldController : Controller
{
    public ViewResult Index()
    {
        return View();
    }

}

And we’ll create the corresponding view for our Index action:

<%@ Page Title="Hello from C#!" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Hello from C#!
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Hello, World!</h2>
    <p>This is a view from a portable area created in C#!</p>
    <p>The current time is <%=DateTime.Now.ToShortTimeString() %></p>

</asp:Content>

When creating the view, go ahead and specify the master, but note that at runtime the view will actually use the master from the parent project, not the Portable Area project.  We left the master view in the Portable Area project so that the views we create will have the correct content placeholder IDs (more on this later). 

The last thing we need to do to complete our portable area is add a registration class:

public class HelloWorldRegistration : PortableAreaRegistration
{
    public override string AreaName
    {
        get { return "HelloWorld"; }
    }

    public override void RegisterArea(AreaRegistrationContext context, IApplicationBus bus)
    {
        context.MapRoute("HelloWorld", "helloworld/{action}",
                         new { controller = "helloworld", action = "index" });

        RegisterAreaEmbeddedResources();
    }
}

Registration is fairly simple: we give our area a name, map a route to it, and call a base class method to register all the embedded resources for our Portable Area.

Visual Basic: Say Hello to C#!

So far we have a Visual Basic WebForms application and  C# MVC application, but the two aren’t playing in the same sandbox yet.  In the WebForms application, add a project reference to the C# MVC application.  Visual Studio will kindly let us do this because an MVC project is really just a class library project underneath all the bells and whistles.  

Build and launch your WebForms app.  It should take you to Default.aspx, which is a regular WebForms page.  Now, try navigating to the controller we created in C# by appending “/helloworld” to the URL.  If I’ve described the steps correctly, you should be greeted with something like the following:

CSharpPortableArea1

Our WebForms app is routing requests to the controller we defined in C#, and the embedded view engine is returning the corresponding view.  Do note, though, that our view is being rendered using our VB MVC view master page, and not the view master page from our C# Portable Area.  That’s by design: Portable Areas are designed to be plugged in and reused within an application.  In this case though, we’d actually like for our C# view to use the same WebForms master page as our existing WebForms content; we don’t want to maintain two distinct master pages.  It turns out that you can do this quite easily.

C# View, Meet VB WebForms Master Page

Examining our view again, we see that it provides content for two placeholders: TitleContent and MainContent.  These placeholders match the standard MVC view master page that we added to our WebForms project under ‘~/Views/Shared/Site.Master’.  If you open up the WebForms master at ‘~/Site.master’ though, you’ll notice that it defines only HeadContent and MainContent.  Let’s add a TitleContent placeholder so that our views can still define their own page titles in the usual MVC way:

<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server"/></title>
    <link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
    <asp:ContentPlaceHolder ID="HeadContent" runat="server">
    </asp:ContentPlaceHolder>
</head>

Next, go back our view in the Portable Area, and change its MasterPageFile property to ‘~/Site.master’.  If you are using Resharper, you’ll notice errors indicating that there’s no master page file at that location and that your content placeholder IDs are no longer valid.  That’s because as far as Resharper (and Visual Studio) know, you are now referencing a master that doesn’t exist.  The only view master page in the C# project is at ‘~/Views/Shared/Site.master’.  All we need to do is move the master from it’s current location to the root of our C# project, and the errors will go away.  When we create new views in the future, we can reference the view master page at its new location, and our views will be generated with the correct path for our WebForms master.

Rebuild and refresh your application, and you’ll see that the Index view from our HelloWorld controller is now being rendered within the WebForms master, title-and-all:

CSharpPortableArea2

Keep in mind that what I’ve described is a proof-of-concept only; I have not tried applying this to a real project yet, and there are likely to be issues with this approach.  If you do run into issues, I’d like to hear about them.  If you want to checkout my code, you may download the sample project here.

Tags:

Jun 30 2010

RageFeed’s Message Bus

Category: .NETMatt @ 16:00

In my recent post about heavy controller actions in RageFeed, I promised to show more details about how the Message Bus pattern was being employed within RageFeed to facilitate the creation of simple, business-logic-free controllers.  Then I got sidetracked with a new job, CodeStock, travel, and life in general. Since then, the message bus in RageFeed has changed quite a bit.  In this post, I’ll show you how the bus looks today and how it’s implemented. 

As a refresher, recall that the controllers within RageFeed were becoming quite bloated, with code resembling the following:

private readonly IRageFeedMembershipProvider _membershipProvider;
private readonly IEmailDispatcher _emailDispatcher;
private readonly IProfileService _profileService;
private readonly IMembershipService _membershipService;

public SignupController(IRageFeedMembershipProvider membershipProvider, 
    IEmailDispatcher emailDispatcher, 
    IProfileService profileService, 
    IMembershipService membershipService)
{
    _membershipProvider = membershipProvider;
    _emailDispatcher = emailDispatcher;
    _profileService = profileService;
    _membershipService = membershipService;
}
...
public ViewResult Activate(string username, string activationToken)
{
    var profile = _profileService.GetForUser(username);

    if (profile == null || profile.ActivationToken != activationToken)
    {
        return View("ActivationFailed");
    }

    var user = _membershipService.GetUser(username);
    user.IsApproved = true;
    _membershipService.UpdateUser(user);

    return View();
}

By applying the message bus pattern, I was able to simplify the controllers to code that looked more like this:

private readonly IBus _bus;
private readonly IAuthenticationService _authService;

public SignupController(IBus bus, IAuthenticationService authService)
{
    _bus = bus;
    _authService = authService;
}
...
public ViewResult Activate(string username, string activationToken)
{
    var result = _bus.RequestReply<ActivateUserRequest,ActivateUserReply>(new ActivateUserRequest { Username = username, ActivationToken = activationToken });

    if (!result.Succeeded)
    {
        return View("ActivationFailed");
    }

    _authService.SetAuthCookie(username);

    return View();
}

While this isn’t a huge simplification in terms of lines of code, the improvements are still significant.  The business logic is gone and safely encapsulated somewhere on the far side of the bus.  Prior to the change, the tests had to setup expectations on mocks for both the profile service and the membership service.  After the change, the tests only need to setup the appropriate response from the bus.

The bus itself is quite simple:

public class MessageBus : IBus
{
    private readonly IMessageHandlerRegistry _registry;

    public MessageBus(IMessageHandlerRegistry registry)
    {
        _registry = registry;
    }

    /// <summary>
    /// Sends a message that doesn't require a response.
    /// </summary>
    /// <param name="message"></param>
    /// <typeparam name="TMessage"></typeparam>
    public void Send<TMessage>(TMessage message)
    {
        var handler = _registry.GetCommandHandlerFor<TMessage>();

        if (handler == null)
        {
            throw new HandlerNotFoundException(typeof (TMessage));
        }

        handler.Handle(message);
    }

    /// <summary>
    /// Sends a message and gets the reply. 
    /// </summary>
    /// <typeparam name="TRequest"></typeparam>
    /// <typeparam name="TReply"></typeparam>
    /// <param name="request"></param>
    /// <returns></returns>
    public TReply RequestReply<TRequest, TReply>(TRequest request)
    {
        var handler = _registry.GetCommandHandlerFor<TRequest,TReply>();

        if (handler == null)
        {
            throw new HandlerNotFoundException(typeof (TRequest), typeof (TReply));
        }

        return handler.Handle(request);
    }
}

It uses a registry to find appropriate command handlers, then dispatches the incoming message to the handler.  For request/reply scenarios, it returns the reply from the handler back to the original caller.  The registry is nothing more than a wrapper around StructureMap:

public class MessageHandlerRegistry : IMessageHandlerRegistry
{
    private readonly IContainer _container;

    public MessageHandlerRegistry(IContainer container)
    {
        _container = container;
    }

    public ICommandHandler<TMessage> GetCommandHandlerFor<TMessage>()
    {
        return _container.GetInstance<ICommandHandler<TMessage>>();
    }

    public IMessageHandler<TRequest, TReply> GetCommandHandlerFor<TRequest, TReply>()
    {
        return _container.GetInstance<IMessageHandler<TRequest, TReply>>();
    }
}

Note: I don’t like the names ICommandHandler and IMessageHandler, they’re going to be renamed soon(ish).

By leveraging StructureMap, command handlers can be automagically registered for the appropriate request/reply types, so adding and subscribing a command handler becomes as simple as creating a class that implements an appropriate interface:

public class CheckEmailAvailabilityHandler : IMessageHandler<CheckEmailAvailabilityRequest, CheckEmailAvailabilityReply>
{
    private readonly IUserRepository _repository;

    public CheckEmailAvailabilityHandler(IUserRepository repository)
    {
        _repository = repository;
    }

    public CheckEmailAvailabilityReply Handle(CheckEmailAvailabilityRequest request)
    {
        var isInuse = _repository.GetByEmail(request.Email) != null;

        return new CheckEmailAvailabilityReply {IsInUse = isInuse};
    }
}

Organizing the business logic this way makes it far easier to create small, reusable, easily-testable, and loosely-coupled nuggets of logic. 

One final note, I’m trying to follow the principles of the “onion architecture” as well as the “folder-per-feature” used by Ayende.  This means that each major feature in RageFeed will have it’s own folder (namespace) within Core, as illustrated below.

FeatureOrganization

I’m still not completely satisfied with this breakdown.  It feels “wrong” to have the messages living side-by-side with the handlers, but according to the onion architecture, it’s fine for the web layer to depend on core.  Even so, I’m considering breaking the message off into a separate namespace or project, but it does make it easier to find what you’re looking for when everything related to the implementation of a feature is contained in a single folder as it is now. If you have suggestions for better ways to organize things, please do share.

If you are familiar with MVCContrib, you should be wondering why I chose to implement my own bus instead of leveraging the bus that’s available in MVCContrib.  I have good reasons for that, but that’s a topic for another day.  In a future post (to be published sometime before the dinosaurs return in 2012), I’ll compare the RageFeed bus with the MVCContrib bus and highlight the pros and cons of each.  Until then, let me know what you think in the comments!

Tags:

Jun 27 2010

My “NHibernate.Search and Lucene.NET” Presentation from CodeStock 2010

Category: Lucene | SQL | NHibernateMatt @ 15:36

CodeStock 2010 is over. I had a good time, talked with lots of cool people, and attended some great sessions.  Though I had to miss day 1 due to commitments for my new job at TrackAbout, I was able to attend and present on day 2.  I’d like to thank everyone that attended my presentation, and I hope everyone took something useful away from it.

I’ve uploaded my slides and code, so if you missed the session and are curious what was covered, or if you attended and want to see it again, check out the links below.  The slide deck is a little sparse on content since most of the session was me talking and writing code, but I’m working on a few blog posts that will fill the gaps (and possibly more).  Anyway, check out the links, and let me know if you have any questions or comments!

Adding powerful search capabilities to your application with Lucene.NET and NHibernate Search
Slides
Code

Tags:

May 30 2010

Welcome to the new try-catch-FAIL!

Category: MiscMatt @ 08:31

After several years of limping by with a subpar layout, I finally have a nice(ish) theme!  To go along with that, I’ve made several other changes to the bog. 

I decided not to abandon BlogEngine.net.  While there are alternatives, each has some serious drawbacks, and in the end, my biggest complaint with BlogEngine.net was the lack of useful CAPTCHA, which was fixed in 1.6.1. 

Another change is the switch to Disqus for comments.  While the new BlogEngine.net build does have reCAPTCHA built-in, I still wanted something a little nicer, and Disqus looks quite promising.  Let me know what you think.

Other than that, I suppose not much has really changed… yet.  I’ll be revamping a few other things as time allows, such as add a real bio page, cleaning up the categories, and other long-neglected housekeeping.  In the meantime, let me know what you think of the new layout!

Tags:

May 20 2010

Comments disabled

Category: MiscMatt @ 06:14

Comments are disabled until I find time to migrate this blog off of BlogEngine.net.  The volume of spam comments has hit intolerable levels.  If you wish to comment on a post, please E-mail me instead.

Tags:

May 17 2010

Heavy controller actions? The Message Bus Pattern to the rescue!

Category: .NETMatt @ 15:39

I recently derailed (badly) while working on a simple requirement for RageFeed: new user registration.  We decided to use the baked-in ASP.NET membership and profile providers, and I found myself adding a lot of code to facilitate the registration workflow.  This was a problem in and of itself, but I realized I had a bigger problem when I stopped and looked at the tremendous number of test cases for my controller.  I had drifted so slowly into a bad design that I didn’t even realize it was happening until it was too late.  Fortunately, all was not lost.  A design pattern from the distributed computing domain came to save the day.

RageFeed, the super-secret project that I have been only murmuring about from time to time for the last couple of months, is trudging along slowly.  Most of the infrastructure is in place and working, so work has turned towards implementing real, honest-to-goodness features.  The first thing I tried to tackle was new user registration; after all, what good are features without users to (ab)use them?  Our team decided that we wanted users to be able to get in and “raging” as quickly as possible.  The workflow would be like this:

  • User registers with their E-mail address and is given immediate (restricted) access.
  • A verification E-mail is sent to the user.
  • The user clicks a verification link that redirects to the system.
  • The system prompts the user to create a password.
  • The user is given full access to the system.

Knowing that the baked-in ASP.NET membership and profile providers were fairly rigid and not really all that well matched to ASP.NET MVC, we still naively assumed that we would be able to bend them to meet this non-standard workflow.  That was certainly a mistake in hindsight (which I’ll probably blog about later), but it led a bigger problem: bad code. In my push to “get the frickin’ users in the system”, I had lowered my guard and tried to brute force my way through the story.  I knew things were starting to go awry when the unit tests for the signup controller hit a dozen.  Sure, the user registration workflow is a bit complicated, but most of the complexity is business logic, not something that belongs in the controller. 

If I wasn’t so focused on “get it done, now”, I think I would have realized my approach was flawed from the beginning.  Some of the tests were difficult to write and required setting up expectations on multiple services.  This testing friction is usually a good sign that you need to rethink your approach.  In fact, I’d argue that a controller with more than a couple service dependencies needs to be redesigned anyway.  Coding to interfaces and using dependency injection does eliminate your coupling to concrete types, but the interfaces themselves still introduce coupling, and coupling should be kept to a minimum.

The Problem

Let’s look at the constructor for my original implementation of the SignupController:

private readonly IRageFeedMembershipProvider _membershipProvider;
private readonly IEmailDispatcher _emailDispatcher;
private readonly IProfileService _profileService;
private readonly IMembershipService _membershipService;

public SignupController(IRageFeedMembershipProvider membershipProvider, 
    IEmailDispatcher emailDispatcher, 
    IProfileService profileService, 
    IMembershipService membershipService)
{
    _membershipProvider = membershipProvider;
    _emailDispatcher = emailDispatcher;
    _profileService = profileService;
    _membershipService = membershipService;
}

Yep, it depends on *four* separate services.  At a minimum, this complexity could be hidden behind a facade, but there’s a deeper problem.  You can see it when you look at the Activate action:

public ViewResult Activate(string username, string activationToken)
{
    var profile = _profileService.GetForUser(username);

    if (profile == null || profile.ActivationToken != activationToken)
    {
        return View("ActivationFailed");
    }

    var user = _membershipService.GetUser(username);
    user.IsApproved = true;
    _membershipService.UpdateUser(user);

    return View();
}

See that?  It’s subtle, but it’s there, hiding in plain sight: business logic.  The controller now knows the rules for how a user can be activated (their activation token must match the previously stored activation token) and how to activate them (setting the IsApproved flag to true).  As I was TDDing this method, I created three separate test cases: one to test for a non-existent user (null profile), another for an invalid activation token, and finally one to verify that the user is correctly activated.  Each required at least some setup on the mock services.  This same sort of business logic leak occurred in some of the other signup-related actions, leading to a large test fixture and code that made me cringe. 

The Solution

Instead of containing business logic, my controller action should do nothing more than get data from (or provide data to) the views, and pass it off to the business layer of the system for further processing.  The controller should handle things like user-input validation (via model binding) and determining which view to render, but it shouldn’t make business decisions.  Thinking in very generic terms, the controller should publish a command to the business layer, and something in the business layer that subscribes to the command should process it, returning only the information the controller needs to decide which action result to return.  This is about as loosely coupled as you can realistically get: the controller shouldn’t know (or care) who is processing the command, and the class processing the command shouldn’t care about where the command comes from.

There’s a Pattern For That: the Message Bus. While this pattern has historically been used for communication between applications in a potentially distributed environment, it has gained ground recently as a means of decoupling components within the same physical application.  The MVCContrib project includes a message bus, and numerous blog posts of late have presented various incarnations of this pattern. 

Ignoring how RageFeed’s message bus works, take a look at the revised implementation of the Activate action now:

public ViewResult Activate(string username, string activationToken)
{
    var command = new ActivateUserCommand {Username = username, ActivationToken = activationToken};

    var result = _bus.Send(command);

    if (!result.Succeeded)
    {
        return View("ActivationFailed");
    }

    return View();
}

What was gained?

The action is simpler now, and more importantly, it is completely devoid of business logic.  It just creates the command, sends it, gets the response, and decides which view to render.  No longer is the controller coupled to multiple services, instead it has just a single dependency on the message bus, and that’s it.  The corresponding tests are also simpler: they just need to verify that the expected command was sent, and that the correct view was rendered for both success and failure.  They don’t need to setup expectations on anything except the service bus.  Note that I really didn’t remove any business logic from the system, I just (correctly) encapsulated it in the business layer, leaving the controller free to focus on user interface-related concerns. 

So how does it work?

Good question!  I’ll dive into the details of how the bus is implemented and how the command processor for the ActivateUserCommand is implemented in the next post!  In the meantime, let me know what you think in the comments.

Tags:

May 13 2010

Want to be a better developer?

Category: Best Practices | .NETMatt @ 06:44

I've been trying to put together a link list of things that have helped me improve as a developer over the last couple of years.  This is far from complete, but it's a start.  I'm not saying this is an absolute "you have to know these things" list or that it will work for everyone out there, it's just things I've found to be really helpful for me.  As always, your mileage may vary. 

  • SOLID Principles - These principles have helped me a ton.  They aren't rules to be followed blindly, but I've found that understanding the reasoning behind them and trying to strive for code that adheres to them generally makes things easier (and also more fun) in the long run.  Now when I’m faced with a design choice, I usually ask myself which alternative is more SOLID and go with that.  Be sure to check out the SOLID “motivational” posters over at Derick Baily’s blog.
  • Design Patterns – Certain types of problems tend to recur in software development.  For these, we have design patterns.  Getting a handle on design patterns is something that only comes with practice.  You won’t be able to memorize and recognize even the “core” set of patterns immediately, but over time you will likely find yourself recognizing when to apply them more and more often. I strongly recommend Head First Design Patterns (yes, the code samples are in Java, but the patterns themselves are what’s important, and a C# dev should have no problem following along).  It provides a very good introduction to design patterns.
  • Test Driven Development – I think a lot of new developers hear “testing” and immediately glaze over, but I actually enjoy practicing TDD.  It doesn’t just help me test my code, it helps me design my code.  That’s a big advantage that a lot of people overlook.  It also gives me confidence that the class I’m creating does exactly what it is supposed to do, and nothing more.  If you aren’t sure how to do TDD, you can watch one of the various TDD Katas online, such as the String Calculator at Roy Osherove’s site or the Bowling Game at ‘Uncle’ Bob’s site. 
  • Resharper 5 - Resharper is essential for doing C# development in my opinion.  Out of the box, it will suggest lots of little things that can help improve your code.  It helped me learn LINQ by offering to convert ugly for/foreach loops into clean, elegant LINQ expressions, and it finally convinced me that ‘var’ isn’t always evil. 
  • NHibernate and FluentNHibernate - I prefer NHibernate to Castle ActiveRecord these days; the ActiveRecord pattern isn't as flexible or as extensible as an implementation of the repository pattern based on NHibernate, and I’ve run face first into that wall on more than one occasion.  FluentNHibernate makes it a lot easier to get up and running with NHibernate since it hides the XML and provides other nice helpers to get you started.  
  • Lambda expressions - These are essential when working with C# 3.0 or later.  They're a bit hard to grasp at first, but they open up very interesting re-use possibilities, and lots of APIs leverage them heavily. FluentNHibernate uses them to setup mappings, and StructureMap uses them for its embedded Domain-Specific Language (DSL). 
  • Generics - This is an older C# feature, but understanding generics is still just as essential today as ever.  Beyond leveraging the built-in generic classes from the base-class library, learning to wield generics also opens up new avenues for creating clean, extensible, and reusable classes.
  • StructureMap (including its AutoMocking container) - One of the biggest "lightbulb" moments I've had recently was adopting StructureMap and IoC-everywhere.  This totally changed how I code.  Now when I realize a class I'm working on is going to need some other 'service' to fullfill its responsibilities, I simply create a new service interface and add it to my class's constructor.  This makes doing top-down development much easier.  Once I’ve finished the tests and implementation for the class I’m working on, I can turn my attention to creating the class that fullfills the service interface. 
  • LINQ - A lot of people focus on LINQ to SQL, but LINQ is more than that.  LINQ to Objects is incredibly useful. Instead of complicated foreach loops that filter or project objects, I find myself writing short, elegant LINQ queries instead. Be sure you learn about all the various extension methods and keywords, including things like ‘select…into’ and ‘let’. 
  • Moq – Mocking frameworks allow you to configure stubs or fakes that you can substitute for dependencies while testing your classes.  While they can indeed be abused, they are still quite useful.  Moq is my personal favorite for its fluent, lambda-based syntax.  Combine it with the adapter pattern, and you can even use it to fake or stub dependencies on base-class library types.
  • ASP.NET MVC and MVCContrib – If you are going to make an ASP.NET application, do yourself a favor and go the MVC route.  While the drag-and-drop appeal of WebForms can be hard to resist, you will inevitably find yourself fighting its leaky abstractions and lack of flexibility as your application scales.  Out of the box, ASP.NET MVC is still quite bare-bones, and you may find yourself having to focus on issues that are more “plumbing” and less “application”.  Be sure to check MVCContrib before you start reinventing the wheel.  With things like portable areas, fluent control builders, test helpers, and a slew of HtmlHelper extensions, it’s surprisingly easy to build maintainable, testable ASP.NET applications by leveraging MVCContrib and ASP.NET MVC. 

Aside from that, I also follow numerous blogs on development.  If I had to trim Google Reader down to only two dev blogs, they would probably be:

  • Ayende @ Rahien – Creator of more open-source .NET software than probably anyone, Ayende is one of my “code heroes”.  I’ve learned a lot from his blog and by reading the code of his various projects.
  • Los Techies – The number of really smart people blogging here makes it a must-read.  I’ve absorbed a lot of new ideas and information from this place.  

I’m sure I’m overlooking something.  Let me know what you’ve found most helpful in improving your developer chops in the comments.

Tags: