Thursday, 2 December 2010

Verifying that Windsor is configured correctly

Yesterday I experienced some very weird behaviour in an MVC app I am building - and it all came down to me being sloppy when configuring Windsor to resolve instances of HttpContextBase. In my haste I'd left the lifestyle configuration as default, rendering the resolved HttpContextWrapper as a singleton. That's not particularly useful.

When this happened it occurred to me that it would be nice to be able to verify that you've configured Windsor in the correct way and that you haven't inadvertently changed that configuration during development. So I knocked up a couple of extension methods on IWindsorContainer that can help. With these you can run tests such as:


_container.ShouldMap<IDisposable>().To<MyClass>();
_container.ShouldMap<IDisposable>().To<MyClass>().WithLifeStyle(LifestyleType.PerWebRequest);
_container.ShouldMap<HttpContextBase>().WithLifeStyle(LifestyleType.Singleton);

All you need is an instance of IWindsorContainer and the extension methods below. Note, that if you're testing stuff that's environment dependent (i.e. resolving HttpContext which is dependent on the ASP.NET runtime) you'll have to set that up separately. Lastly, I've built this against NUnit - but refactoring to other frameworks should be easy.

public static class ContainerExtensions
{
public class ComponentWrapper
{
public IWindsorContainer Container { get; set; }
public ComponentModel Component { get; set; }
}

public static ComponentWrapper ShouldMap<T>(this IWindsorContainer container) where T : class
{
List<GraphNode> graphNodes = new List<GraphNode>(container.Kernel.GraphNodes);
List<ComponentModel> componentModels = new List<ComponentModel>(Convert(graphNodes));

ComponentModel componentModel = componentModels.Find(x => x.Service == typeof(T));
if (componentModel == null)
throw new AssertionException(string.Format("Service {0} has not been registered in the container",
typeof (T).FullName));

return new ComponentWrapper {Container = container, Component = componentModel};
}

public static ComponentWrapper To<T>(this ComponentWrapper wrapper) where T : class
{
Type serviceType = wrapper.Component.Service;
try
{
var instance = wrapper.Container.Resolve(serviceType);

if (instance.GetType() != typeof(T))
throw new AssertionException(string.Format("Expected implementation of {0} to be {1}, but was {2}",
serviceType,
typeof(T).FullName, instance.GetType()));
}
catch(Exception exception)
{
throw new AssertionException(string.Format("An exception was thrown when resolving {0}. The exception message is: {1}",
serviceType, exception.Message), exception);
}

return wrapper;
}

public static ComponentWrapper WithLifeStyle(this ComponentWrapper wrapper, LifestyleType expectedExpectedLifestyle)
{
VerifyLifestyle(wrapper.Component.LifestyleType, expectedExpectedLifestyle);
return wrapper;
}

private static void VerifyLifestyle(LifestyleType actualLifestyle, LifestyleType expectedLifestyle)
{
if (actualLifestyle == LifestyleType.Undefined && expectedLifestyle == LifestyleType.Singleton)
return;

if(expectedLifestyle != actualLifestyle)
throw new AssertionException(string.Format("Expected lifestyle {0} but was {1}",
expectedLifestyle, actualLifestyle));
}

private static IEnumerable<ComponentModel> Convert(List<GraphNode> graphnodes)
{
foreach(GraphNode node in graphnodes)
yield return node as ComponentModel;
}
}

Tuesday, 30 November 2010

Encapsulating boolean return types.

.Net 4 introduced some changes to the way DataAnnotations ValidationAttributes work. Pre .NET 4 you would check the validity of a property on a class by attributing it with a ValidationAttribute (custom or otherwise) and then calling the IsValid():bool method. This is straight forward and logical. However; this approach leaves a bit to be desired. If IsValid() returns false, what exactly is it that invalidates my property? It would be better if validation was approached differently, and this is what DataAnnotations in .NET 4 does.

In .NET 4 the use of IsValid():bool is discouraged. In fact, if you create a new custom validation attribute (extending ValidationAttribute) and do not override IsValid() before you call it, it will throw a NotImplementedException with the message "IsValid(object value) has not been implemented by this class. The preferred entry point is GetValidationResult() and classes should override IsValid(object value, ValidationContext context)."

As you can see, you're encouraged to override an overload of IsValid(). If you look closer you'll see that the overload does not return true/false, but instead returns a ValidationResult which is a wee bit more informative. Also, the overload is protected - so you can't call it externally. Instead you call the GetValidationResult() method to see what the result of validation is.

Why is this better than just returning true or false? It's because a ValidationResult carries information about why validation failed.

You might now think that this is a bit overkill for scenarios in which validation is successful. In this case, more often than not, all you care about is knowing that validation has passed and that you can carry on. The ValidationResult class facilitates this by applying the Null Object Pattern and encapsulating a static property called ValidationResult.Success against which you can compare the ValidationResult instance returned to you by GetValidationResult() (ValidationResult.Success always returns null, because a null validation result signifies successful validation).

This approach doesn't just apply to validation scenarios. Ayende Rahien talks about why and how he uses this approach here. If you have a method that returns true/false and there is no more relevant information available, fine. However, if the true/false answer masks other information then the approach of encapsulating the answer in a class is better.

Monday, 29 November 2010

Go on. Get NuGet.

I spent most of yesterday afternoon (Sunday!) messing about with FluentNHibernate, trying to compile the source to .NET4, NHibernate 3 Beta, and Castle Windsor 2.5.

What. A. Waste. Of. Time.

Sometimes I just don't think. Somebody out there would probably have done this already, right? The answer to that question is yes. But it wasn't until I happened upon the hornget project that bells started ringing: "Hmmmm.... that's awfully similar to NuGet, isn't it?" Yes, it is.

Suffice to say that 10 minutes after this realisation I had FluentNHibernate running in my solution, with NHibernate 3 Beta and Castle Windsor 2.5.

So if you haven't already, go on and get NuGet.

Thursday, 25 November 2010

Testing routes with MVC3 RC1 and .NET 4

Yesterday I found myself needing to test some MVC routes. I wanted to avoid setting up all the mocking infrastructure needed to do so, and decided to use the MVCContrib project to ease the work. However, I am building an MVC 3 RC1 app on .NET 4 - and MVCContrib targets .NET 3.5 and MVC 2, so I quickly ran into trouble.

I tried converting the solution to .NET 4.0 - but it was too time consuming to do so. Instead I ripped out the pieces I needed, i.e. the route testing extension methods, and built a new assembly targeting the right versions of the framework. And I replaced RhinoMocks with Moq.


Using the Mvc.TestHelper assembly you can easily test routes with syntax like this:
"~/".ShouldMapTo<HomeController>(x => x.Index());
"~/Account/".ShouldMapTo<AccountController>(x => x.Register(null));

Note: I take zero credit for this work. All the source code is taken directly from the MVCContrib project.

I have made the source available on BitBucket so that you can test your MVC 3 routes. The project uses NUnit and Moq for testing.

Thursday, 21 January 2010

The LIBUSWKAIQ anti-pattern

Design patterns have been all the rage for quite some time now, and with them have come an increased awareness of patterns that pretend to be design patterns but really are anti-patterns; a pattern that appears obvious but really is far from optimal in practice (read: stupid).

A relatively recent (and greenfield) implementation where I work is built around such an anti-pattern. We've named this lovely piece of instant legacy the LIBUSWKAIQ anti-pattern. It's pronounced "Libbus-wah-cake" and stands for "Let It Blow Up So We Know About It Quickly."

  • This pattern gives you free license to forget about exception handling and encourages applications to fall over and die if any exceptional circumstances arise.
  • This pattern encourages you to throw exceptions with the explicit purpose of killing your app.
  • This pattern hates error handling.
  • This pattern creates needy applications that require immediate attention.
  • This pattern encourages 3am support calls. This pattern wants your support developers to always be deprived of sleep. This patterns wants you to spend your ENTIRE support budget.
  • This pattern appeals to lazy people.

Don't do this! Handle your errors. Keep your apps running. Put errors to the side and let humans deal with it as soon as it is conveniently possible. Don't stop your entire business process running just because it experienced a minor 'blip.'

You're smarter than this. Don't get sucked into becoming a Libbus-wah-caker.