Convention-based IOC is great … if everyone follows the conventions

Recently I started using Ninject for Inversion Of Control (IOC) and Dependency Injection (DI) on an ASP.Net MVC3 project.  Ninject is a very neat framework and is easy to use BTW and its offers some slick MVC3 integration through the Ninject.Web.Mvc project.

Being a proponent of convention-over-configuration, I also looked for some auto-registration code for Ninject and soon found the Ninject.Extensions.Conventions project.  The default convention here also suits me, since it binds IFooService to FooService in transient scope. Using the Scan extension method, I could now have the following code to initialise my IOC:

kernel.Scan(scanner =>
{
    scanner.FromAssemblyContaining<ProjectRepository>();
    scanner.BindWith<DefaultBindingGenerator>();
});

So far, so good, I thought, and now to apply IOC to my WCF services, which are hosted within the MVC web project (important point!).  Once again, Ninject has an answer, in the form of the Ninject.Extensions.Wcf project.  This project offers a custom ServiceHostFactory that will apply IOC to your service implementation simply by adding the Factory attribute in your .svc file:

<%@ ServiceHost Language="C#" 
                Debug="true" 
                Service="SharpFellows.ScrumToolkit.Web.Services.Authentication" 
                CodeBehind="Authentication.svc.cs" 
                Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %>

Very nice … except that it didn’t work (yet).  This didn’t surprise me much at this stage because both Ninject.Web.Mvc and Ninject.Extensions.Wcf define a custom HttpApplication class and both libraries expect you to derive from this in your global.asax.cs class.  I opted to keep the class for Mvc and patch in the functionality required by the class for Wcf.  [As an aside, this is only possible because of the nature of open source software – hurray for open source]  So here was my first attempt:

kernel.Scan(scanner =>
{
    scanner.FromAssemblyContaining<ProjectRepository>();
    // Ninject.Extensions.Wcf uses some binding internally
    scanner.FromAssemblyContaining<NinjectServiceHostFactory>();
    scanner.BindWith<DefaultBindingGenerator>();
});
// Ninject.Extensions.Wcf expects to find the kernel here
KernelContainer.Kernel = kernel;

Looking good … except that it still didn’t work.  Requests to the WCF service were now all met with this:

The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.

After much head-scratching, it turns out that the IOC binding done internally by the Ninject.Extensions.Wcf project is to bind ServiceHost to NinjectServiceHost and this binding does not follow the default conventions laid down by Ninject.Extensions.Convention!  Obvious really, once you understand the conventions and look at the required binding.  So now the fix was pretty simple:

// Conventions pick up most of our IOC bindings  :-)
kernel.Scan(scanner =>
{
    scanner.FromAssemblyContaining<ProjectRepository>();
    scanner.BindWith<DefaultBindingGenerator>();
});

// This binding doesn't follow the convention  :-/
kernel.Bind<ServiceHost>().To<NinjectServiceHost>();

// Ninject.Extensions.Wcf expects to find the kernel here
KernelContainer.Kernel = kernel;

And now everything worked smoothly.  Smile

The moral of the story?  It is possible to get MVC controllers and WCF service classes controlled by the same Ninject kernel.  And if you use conventions, don’t assume that all libraries can and do use them!

June 2 2011

BDD Antipattern: Specs with concealed intent

A great benefit of Behaviour Driven Development (BDD) is that the unit tests become the primary way of documenting the functionality of a system.  In fact, this why in BDD, “tests” are usually referred to as “specifications” or “specs”.  However, developers need to ensure that the intent of their spec is clearly evident and revealed.

Consider, for a moment, the following spec:

Given my test data
When my analysis is run
Then the results should be correct

It’s impossible to draw any conclusions from this about the functionality of the system, without being able to see the implementation details of this spec.  Let’s suppose that the step implementation details are as follows:

[ActionSteps]
public class DataAnlaysisSteps
{
    private AverageCalculator _calculator;

    [BeforeScenario]
    public void SetupContext()
    {
        _calculator = new AverageCalculator();
    }

    [Given("my test data")]
    public void InsertTestData()
    {
        _calculator.RecordValue(10);
        _calculator.RecordValue(20);
    }

    [When("my analysis is run")]
    public void Analyse()
    {
        _calculator.PerformAnalysis();
    }

    [Then("the results should be correct")]
    public void CheckResults()
    {
        Assert.AreEqual(15, _calculator.Result);
    }
}

If you read through this in detail, then you can probably guess that we are testing some code that computes average values.  Now there is no reason that our spec cannot make this clear:

Given my test data
When the average value is computed
Then the average value should be computed correctly

This is certainly an improvement, albeit a small one.  Language in BDD specs is quite important (as I’ve mentioned previously).  However, it’s impossible to extend this spec to test other datasets and it’s still not entirely clear what we mean by “computed correctly”.  Let’s address this:

Given a value of 10
And a value of 20
When the average value is computed
Then it should be 15

With this spec, there is no doubt about its purpose and the expected behaviour of the underlying system.  It’s also easy to see how we could add more specs to validate the behaviour with other datasets.  For those who are interested, the step implementation details are as follows:

[ActionSteps]
public class DataAnlaysisSteps
{
    private AverageCalculator _calculator;

    [BeforeScenario]
    public void SetupContext()
    {
        _calculator = new AverageCalculator();
    }

    [Given("a value of $n")]
    public void RecordData(int n)
    {
        _calculator.RecordValue(n);
    }
    
    [When("the average value is computed")]
    public void Analyse()
    {
        _calculator.PerformAnalysis();
    }

    [Then("it should be $result")]
    public void CheckResult(int result)
    {
        Assert.AreEqual(result, _calculator.Result);
    }
}
April 28 2011

BDD Antipattern: The technical spec (or why geeks need to speak business)

Crash: "What's that sound?"
Buck: "It's the wind, it's speaking to us."
Eddie: "What's it saying?"
Buck: “I don't know…I don't speak wind."
                         from Ice Age: Dawn of the Dinosaurs

BDD is a pretty well-known and well-understood technique in this day and age, and it’s benefits have been described by many (here, here and here, for example).  A number of these benefits hinge on language and communication, and it turns out that these can be quite easily diluted.  Take this specification, for example:

Given my account is in credit
And my card is valid
And the dispenser contains cash
When I request cash
Then my account should be debited
And cash should be dispensed
And my card should be returned

This is highly readable, even though it contains domain-specific terms (“account”, “credit”, “valid”, “card”, “dispenser”).  Consider now this specification, what I call a technical spec:

Given the CreditValidator returns true for my account
And the CardValidator returns true for my card
And the DispenserStatus service returns CashGreaterThanZero
When the DispenserCashRequested event is raised
Then the RecordDebitTransaction of the AccountService should be invoked
And the EjectCash command should be raised on the command broker
And the EjectCard command should be raised on the command broker

While this may be describing the same thing, the wording is technical and tightly coupled to the actual implementation.  Implementation is a technical detail and not a feature of the business process, and in fact it generally changes more frequently than business process.  So this “technical spec” is simultaneously harder to read and more brittle than the spec that was expressed in business language.  Definitely a BDD anti-pattern.

April 12 2011

A random walk in Rx

A random walk can be defined as “a stochastic process consisting of a sequence of changes each of whose characteristics (as magnitude or direction) is determined by chance”.  Or to put it another way, from a starting point, keep adding (or subtracting) random numbers … the resulting stream of numbers is a random walk.

Now I recently needed to demonstrate some graphing capability and decided that I would plot a continuous random walk.  Here was my first attempt:

public class RandomTickDataService : IRandomTickDataService
{
    private readonly IObservable<double> _randomWalk;

    public RandomTickDataService()
    {
        var rnd = new Random();
        _randomWalk = Observable.Interval(TimeSpan.FromMilliseconds(500))
                                .Select(l => (rnd.NextDouble() - 0.5)*2)
                                .Scan((d, d1) => d + d1);
    }
    public IObservable<double> Tick
    {
        get { return _randomWalk; }
    }
}

This did OK until I added a second graph and noticed something odd.  What was happening was that each graph was different even though my IOC (MEF) was configured to create this service as a singleton (CreationPolicy.Shared).  And then I realised that the two graphs subscribing to the Tick property were each generating their own stream of data, since the Observable.Interval does not start until someone subscribes to it (and then it starts again when someone else subscribes to it).  So my second attempt hinged on the Publish method, which allows an observable stream to be reused:

public class RandomTickDataService : IRandomTickDataService
{
    private readonly IConnectableObservable<double> _randomWalk;
    private IDisposable _connection;

    public RandomTickDataService()
    {
        var rnd = new Random();
        _randomWalk = Observable.Interval(TimeSpan.FromMilliseconds(500))
                                .Select(l => (rnd.NextDouble() - 0.5)*2)
                                .Scan((d, d1) => d + d1)
                                .Publish();
    }
    public IObservable<double> Tick
    {
        get
        {
            if(_connection == null)
                _connection = _randomWalk.Connect();
            return _randomWalk;
        }
    }
}

The Tick property has gotten a bit ugly here and I wasn’t quite sure why I had this disposable instance kicking around.  It turned out that while my two charts now plotted the same stream of numbers, the numbers didn’t stop even when I closed all my charts.  #Fellow Andy pointed me in the direction of the RefCount method and so here is my final code (which is neater works nicely):

public class RandomTickDataService : IRandomTickDataService
{
    private readonly IObservable<double> _randomWalk;

    public RandomTickDataService()
    {
        var rnd = new Random();
        _randomWalk = Observable.Interval(TimeSpan.FromMilliseconds(500))
                                .Select(l => (rnd.NextDouble() - 0.5)*2)
                                .Scan((d, d1) => d + d1)
                                .Publish()
                                .RefCount();
    }

    public IObservable<double> Tick
    {
        get { return _randomWalk; }
    }
}
Newer Posts Older Posts