Query Encapsulation Comes Full Circle

August 17, 2010 Neal Leave a comment

I’ve just about finished migrating a bunch of code from using LINQ based queries against my IRepository, which follows this approach discussed by Fabio Maulo, to enhanced query objects, which follow this pattern; again from the formidable mind of Fabio Maulo.

As I was writing the queries, I realised that I was effectively encapsulating the query logic into a self contained object, which is not unlike what a stored procedure does.  So here I am, 10 years or so after I started encapsulating my queries in stored procedures and some 2 or 3 years after giving up stored procedures, encapsulating my queries again.

But why the change?

While LINQ queries work well in small simple cases, you rapidly come to understand that it is effectively the lowest common denominator for working with your ORM (I prefer NHibernate but it applies as well to most others).  The workaround for this is to use a bunch of extension methods meaning you end up referencing your ORM from your service layer which (rightly or wrongly) makes me feel ill.  Enhanced Query Objects allow you to leverage the native power of your ORM while proving a suitably minimalistic interface which greatly increases SoC and simplifies testing of the query consumers.  The implementation also allows the queries to be thoroughly tested in isolation without too much difficulty.

Categories: NHibernate

My Git – Svn Workflow

April 26, 2010 Neal Leave a comment

Since updating msysgit to 1.6.5.1, I have been able to drop the custom cherrypick script I was using to commit back to my subversion repository and finally use the “proper” git – svn workflow. I’m writing it up here because every so often I forget bits of it.

My usual development workflow is based around doing all development in a topic branch.

1.  Ensure master is up to date
      -  git svn rebase
2.  Create a topic branch and switch to it
      -  git checkout -b [topic branch]
3.  ... write some code ...
4.  Commit to local git topic branch ( I use git extensions usually )
      -  git add .
      -  git commit -a -m [commit message]

When I have completed developing a feature and need to check it in to the subversion repository, I use the following workflow:

1.  Ensure master is up to date
      - git checkout master
      -  git svn rebase
2.  Rebase the topic branch to master - this ensures your topic branch is a continuation of the current master branch and will fit better with subversions linear "view" of the world
      -  git checkout [topic branch]
      -  git rebase master
3.  Merge the topic branch onto the master - because of the rebase in the porevious step creating a common ancestor, this will be a fast forward merge
      -  git checkout master
      -  git merge [topic branch]
4.  Commit to the subversion repository
      -  git svn dcommit
5.  Delete the topic branch ( assuming that the dcommit was successful, if the dcommit failed DO NOT delete the topic branch )
      - git branch -D [topic branch]

Sometimes msysgit barfs, usually when committing a large number of local commits to subversion. To fix a broken dcommit, resync the subversion master and topic branch repositories and continue with the dcommit as shown below.

1.  Clean up any staged / unstaged files left by the broken dcommit
      -  git checkout master
      -  git reset head --hard
      -  git clean -d -f
2.  Ensure the master is up to date with the subversion repository
      -  git svn rebase
3.  Resync the master and topic branch
      -  git checkout [topic branch]
      -  git rebase master
4.  Merge any remaining changes onto master
      -  git checkout master
      -  git merge [topic branch]
5.  Resume committing changes to the subversion repository
      -  git svn dcommit
Categories: Git

Why software development metaphors always fail

December 10, 2009 Neal Leave a comment

When discussing concepts in the software development space, we resort to metaphors to compare the concept to something in a different, well known, area because we lack the appropriate ( or shared ) vocabulary to communicate the concept. These metaphors (technically similes) always fail at some point and that is due to something that few (if any) other professions face.

When you visit your mechanic to discuss a problem with your car and tell him about the weird clicking noise it makes when you turn hard left or right, he knows this usually means a dead CV joint.  When you visit your local software developer and ask them to build you a system to show your clients various reports about half hourly meter data,  he will look at you quizzically and ask “What’s half hourly metering?”

This is the key difference between a mechanic and a software developer, you talk to the mechanic about a problem in a domain he understands well, all he has to do is ask the right questions to understand the problem.  You talk to a software developer about a problem domain you understand well, and he has to first understand enough about the domain to be able to ask the right questions.

Software development covers a wide range of job roles, but they all exist to create a limited representation of the clients problem domain in a virtual space (hopefully to solve a problem).  I can’t think of any other professional group that faces this challenge, and the metaphors we use for software development all fail at communicating this to the people we are talking to:

Before I can solve your problem, I must first understand the problem domain

Categories: Philosophy

Using Machine.Specifications with nant

October 20, 2009 Neal 1 comment

Wasted at least an hour today trying to track down an issue running my specs with NAnt. Turns out the problem was using <arg value=”{assembly1} {assembly 2}”  instead of <arg line=”{assembly1} {assembly2}” />.

The subtle difference between value and line is that value allows spaces and presents this to the exe as one argument by quoting the content of the attribute, whereas line passes the content of the attribute as it appears ( so the console runner sees 1 arg in the form “{assembly1} {assembly2}” instead of 2 separate args).  This problem presents itself as an error containing the following text :

Missing Assembly: {assembly1} {assembly2}

The xml for running machine.specifications with NAnt is:

    <target name="test.mspec" unless="${test.skip}">
        <mkdir dir="${test.specreportdir}" />
        <exec program="${test.mspecrunner}"
            basedir="${test.mspecdir}"
            workingdir="${root.dir}">
            <arg value="--silent" if="${teamcity.build}" />
            <arg value="--teamcity" if="${teamcity.build}" />
            <arg value="--html" /><arg dir="${test.specreportdir}" />
            <arg line="${test.assemblies}"/>
        </exec>
    </target>

where:

  • ${test.specreportdir} is the directory for the reports to go into
  • ${test.mspecrunner} is machine.specifications.consolerunner.exe
  • ${test.mspecdir} is the directory containing the mspec console runner
  • ${root.dir} is the root project directory
  • ${teamcity.build} is set from a team city specific build that is used for TC builds
  • ${test.assemblies} is a list of the assemblies containing specs separated by spaces

Simplify IUserType Testing

October 16, 2009 Neal 4 comments

Background

The application I am currently working on makes ( will make ) heavy use of the .NET TimeZoneInfo class to allow us to display times in the current users local time. To achieve this we need to capture and store the timezone from the user.

Capturing the timezone is relatively simple, I use a slightly modified version of this technique used by Nate Kohari’s most excellent Zen.

Storing the timezone provides an interesting choice of options;

I could store the raw offset in hours ( a double ) or in minutes ( an int ) and recreate the TimeZoneInfo each time I want to display a date or time in the users local time. This has the benefit of being incredibly simple and, with a little work to create an extension method, generates almost no duplication except the act of converting the double or int into a TimeZoneInfo.

The second alternative was to let my trusty ORM do the work for me. I use NHibernate and after a little research I found the following articles about creating an IUserType that would allow me to map a TimeZoneInfo into a database field. If you want all the gory details of how to do it go and read those articles, otherwise the code for my TimeZoneInfoUserType is shown at the bottom of the post ( see the section titled The Implementation ).

The Useful Stuff

Normally I use a BDD style approach for building something like this, but as I wasn’t sure how to solve the problem, I spiked out the approach, then added the tests and refined the implementation as required.

Part of spiking out the solution was figuring out how to test it and this initially tripped me up as I was considering mocking IDbCommand and IDataReader ( which gets ugly fast ).

After a little bit of thought, I figured I could use a SqlCommand for the IDbCommand. The following snippet shows what you need to do to use a SqlCommand for testing your NullSafeSet ( note where parameter index comes from ).

_command = new SqlCommand();
_parameterIndex = _command.Parameters.Add( _command.CreateParameter() );

// ... this is then used in the NullSafeSet test ...
_userType.NullSafeSet( _command, null, _parameterIndex );

To find an acceptable IDataReader stand-in, I went poking around with Reflector and found an IDataReader implementation that wraps a DataTable. This gave me a means of quickly and easily controlling the data being passed to the code under test. The following snippet shows how you can set up an IDataReader from a DataTable in as little as 5 lines of code for testing your NullSafeGet ( note the data reader must be “initialised” by calling Read() before using it ):

var dataTable = new DataTable();
dataTable.Columns.Add( ColumnName, typeof( int ) );
dataTable.LoadDataRow( new object[] {TimezoneOffset * 60}, true );
_dataReader = new DataTableReader( dataTable );
_dataReader.Read();

// ... this is then used in the NullSafeSet test ...
_timezoneInfo = (TimeZoneInfo) _userType.NullSafeGet( _dataReader, new[] {ColumnName}, null );

The full source for the TimeZoneInfoUserType and the associated tests is shown below:

The Implementation

    public class TimezoneInfoUserType : IUserType
    {
        public new bool Equals(object x, object y)
        {
            if( ReferenceEquals( x, y ) )
            {
                return true;
            }
            if( x == null || y == null )
            {
                return false;
            }

            return x.Equals( y );
        }

        public int GetHashCode( object x )
        {
            return x.GetHashCode();
        }

        public object NullSafeGet( IDataReader rs, string[] names, object owner )
        {
            var rawValue = NHibernateUtil.Int32.NullSafeGet( rs, names[ 0 ] );
            if( rawValue == null )
            {
                return null;
            }
            var timezoneOffsetMinutes = (int) rawValue;
            var timezoneOffset = new TimeSpan( 0, timezoneOffsetMinutes, 0 );
            return TimeZoneInfoFactory.Create( timezoneOffset.TotalHours );
        }

        public void NullSafeSet( IDbCommand cmd, object value, int index )
        {
            if(value == null)
            {
                NHibernateUtil.Int32.NullSafeSet( cmd, null, index );
                return;
            }
            var timezoneInfo = (TimeZoneInfo) value;
            var offsetInMinutes = timezoneInfo.BaseUtcOffset.TotalMinutes;
            NHibernateUtil.Int32.NullSafeSet( cmd, Convert.ToInt32( offsetInMinutes ) , index );
        }

        public object DeepCopy( object value )
        {
            return value;
        }

        public object Replace( object original, object target, object owner )
        {
            return original;
        }

        public object Assemble( object cached, object owner )
        {
            return cached;
        }

        public object Disassemble( object value )
        {
            return value;
        }

        public SqlType[] SqlTypes
        {
            get { return new[] {SqlTypeFactory.Int32}; }
        }

        public Type ReturnedType
        {
            get { return typeof( TimeZoneInfo ); }
        }

        public bool IsMutable
        {
            get { return false; }
        }
    }

The Tests
Note: If you are wondering about the =()=> sequence, I use MSpec for my testing.

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_saving_a_null_TimezoneInfo
    {
        static int _parameterIndex;
        static TimezoneInfoUserType _userType;
        static IDbCommand _command;

        Establish context = () =>
        {
            _userType = new TimezoneInfoUserType();
            _command = new SqlCommand();
            _parameterIndex = _command.Parameters.Add( _command.CreateParameter() );
        };

        Because of = () =>
            _userType.NullSafeSet( _command, null, _parameterIndex );

        It the_offset_is_stored_as_null = () =>
            ((IDataParameter)_command.Parameters[ _parameterIndex ]).Value.ShouldEqual(DBNull.Value);
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_saving_a_TimezoneInfo_with_a_zero_offset
    {
        static int _parameterIndex;
        static TimezoneInfoUserType _userType;
        static IDbCommand _command;
        static TimeZoneInfo _timezoneInfo;

        Establish context = () =>
        {
            _timezoneInfo = TimeZoneInfoFactory.Create( 0 );
            _userType = new TimezoneInfoUserType();
            _command = new SqlCommand();
            _parameterIndex = _command.Parameters.Add( _command.CreateParameter() );
        };

        Because of = () =>
            _userType.NullSafeSet(_command, _timezoneInfo, _parameterIndex);

        It the_offset_is_stored_as_zero = () =>
            ( (IDataParameter) _command.Parameters[ _parameterIndex ] ).Value.ShouldEqual( 0 );
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_saving_a_TimezoneInfo_with_a_positive_offset
    {
        const int TimezoneOffset = 12;
        static int _parameterIndex;
        static TimezoneInfoUserType _userType;
        static IDbCommand _command;
        static TimeZoneInfo _timezoneInfo;

        Establish context = () =>
        {
            _timezoneInfo = TimeZoneInfoFactory.Create( TimezoneOffset );
            _userType = new TimezoneInfoUserType();
            _command = new SqlCommand();
            _parameterIndex = _command.Parameters.Add( _command.CreateParameter() );
        };

        Because of = () =>
            _userType.NullSafeSet( _command, _timezoneInfo, _parameterIndex );

        It the_offset_is_stored_in_minutes = () =>
            ( (IDataParameter) _command.Parameters[ _parameterIndex ] ).Value.ShouldEqual( TimezoneOffset * 60 );
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_saving_a_TimezoneInfo_with_a_negative_offset
    {
        const int TimezoneOffset = -12;
        static int _parameterIndex;
        static TimezoneInfoUserType _userType;
        static IDbCommand _command;
        static TimeZoneInfo _timezoneInfo;

        Establish context = () =>
        {
            _timezoneInfo = TimeZoneInfoFactory.Create( TimezoneOffset );
            _userType = new TimezoneInfoUserType();
            _command = new SqlCommand();
            _parameterIndex = _command.Parameters.Add( _command.CreateParameter() );
        };

        Because of = () =>
            _userType.NullSafeSet( _command, _timezoneInfo, _parameterIndex );

        It the_offset_is_stored_in_minutes = () =>
            ( (IDataParameter) _command.Parameters[ _parameterIndex ] ).Value.ShouldEqual( TimezoneOffset * 60 );
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_retrieving_a_null_TimezoneInfo
    {
        const string ColumnName = "Timezone";
        static TimeZoneInfo _timezoneInfo;
        static TimezoneInfoUserType _userType;
        static IDataReader _dataReader;

        Establish context = () =>
        {
            _userType = new TimezoneInfoUserType();
            var dataTable = new DataTable();
            dataTable.Columns.Add( ColumnName, typeof( int ) );
            dataTable.LoadDataRow( new object[] {null}, true );
            _dataReader = new DataTableReader( dataTable );
            _dataReader.Read();
        };

        Because of = () =>
            _timezoneInfo = (TimeZoneInfo) _userType.NullSafeGet( _dataReader, new[] {ColumnName}, null );

        It returns_null = () =>
            _timezoneInfo.ShouldBeNull();
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_retrieving_a_TimezoneInfo_with_a_zero_offset
    {
        const string ColumnName = "Timezone";
        static TimeZoneInfo _timezoneInfo;
        static TimezoneInfoUserType _userType;
        static IDataReader _dataReader;

        Establish context = () =>
        {
            _userType = new TimezoneInfoUserType();
            var dataTable = new DataTable();
            dataTable.Columns.Add( ColumnName, typeof( int ) );
            dataTable.LoadDataRow( new object[] {0}, true );
            _dataReader = new DataTableReader( dataTable );
            _dataReader.Read();
        };

        Because of = () =>
            _timezoneInfo = (TimeZoneInfo) _userType.NullSafeGet( _dataReader, new[] {ColumnName}, null );

        It the_BaseUtcOffset_is_zero = () =>
            _timezoneInfo.BaseUtcOffset.TotalHours.ShouldEqual( 0d );

        It the_displayname_is_GMT = () =>
            _timezoneInfo.DisplayName.ShouldEqual( "GMT" );
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_retrieving_a_TimezoneInfo_with_a_positive_offset
    {
        const string ColumnName = "Timezone";
        const int TimezoneOffset = 12;
        static TimeZoneInfo _timezoneInfo;
        static TimezoneInfoUserType _userType;
        static IDataReader _dataReader;

        Establish context = () =>
        {
        _userType = new TimezoneInfoUserType();
        var dataTable = new DataTable();
        dataTable.Columns.Add(ColumnName, typeof(int));
        dataTable.LoadDataRow(new object[] { TimezoneOffset * 60 }, true);
        _dataReader = new DataTableReader(dataTable);
        _dataReader.Read();
        };

        Because of = () =>
            _timezoneInfo = (TimeZoneInfo)_userType.NullSafeGet(_dataReader, new[] { ColumnName }, null);

        It the_BaseUtcOffset_is_generated_from_the_number_of_minutes_retrieved = () =>
            _timezoneInfo.BaseUtcOffset.TotalHours.ShouldEqual( TimezoneOffset );

        It the_displayname_follows_the_pattern_GMT_plus_timezone_offset_ = () =>
            _timezoneInfo.DisplayName.ShouldEqual( "GMT+" + TimezoneOffset );
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_retrieving_a_TimezoneInfo_with_a_negative_offset
    {
        const string ColumnName = "Timezone";
        const int TimezoneOffset = -12;
        static TimeZoneInfo _timezoneInfo;
        static TimezoneInfoUserType _userType;
        static IDataReader _dataReader;

        Establish context = () =>
        {
            _userType = new TimezoneInfoUserType();
            var dataTable = new DataTable();
            dataTable.Columns.Add( ColumnName, typeof( int ) );
            dataTable.LoadDataRow( new object[] {TimezoneOffset * 60}, true );
            _dataReader = new DataTableReader( dataTable );
            _dataReader.Read();
        };

        Because of = () =>
            _timezoneInfo = (TimeZoneInfo) _userType.NullSafeGet( _dataReader, new[] {ColumnName}, null );

        It the_BaseUtcOffset_is_generated_from_the_number_of_minutes_retrieved = () =>
            _timezoneInfo.BaseUtcOffset.TotalHours.ShouldEqual( TimezoneOffset );

        It the_displayname_follows_the_pattern_GMT_minus_timezone_offset_ = () =>
            _timezoneInfo.DisplayName.ShouldEqual( "GMT" + TimezoneOffset );
    }
Categories: NHibernate, TDD, Unit Testing

Managing and Testing Component Registrations with Castle Windsor

September 11, 2009 Neal 2 comments

This post is an extension of an earlier post on testing container registrations.  In this post I cover testing again as well as how I manage component registrations to reduce the amount of xml needed and how I automate component registration as much as possible.

First up, the scenario within which I am using a container:

  • ASP.NET MVC application
  • controllers managed via the WindsorControllerFactory from MVCContrib.
  • actions have only 1 parameter and that type is an interface – the container manages the parameter types via a custom model binder.
  • Parameters are 1 of 3 types:
    1. Commands – do something to the domain and return a result that cannot cause side-effects ( ideally immutable but you cannot use structs in views ).
    2. Queries – retrieve data from the system and pack it into a return type that is effectively a view model.
    3. UrlActions – some actions need both commands and queries and must share request state ( form data, query parameters or route parameters ) so until I use special classes that combine commands and queries for this.
  • A custom validation approach that is similar to FluentValidation
  • NHibernate + NHibernateIntegrationFacility + FluentNHibernate

Semi-automatic Component Registration

Using base or marker interfaces allows you to define a few bulk registrations, rather than a large number of fine-grained registrations.  The design of the application outlined above provides four places where I usually add features into the sytem.  Each one of these extension points is identified by a base interface, this makes it easier to find and automatically register the associated components.  The extension points are:

  • Commands – ICommand<T>
  • Queries – IQuery<T>
  • UrlActions – IUrlAction
  • Validators – IValidator<T>

To add a feature ( e.g. logon ), I usually implement a query, a command and two validators.  All of these components are covered by bulk registrations, therefore I don’t have to “remember” to register them in the container before using them – it happens automatically.

public static class ComponentRegistrations
    {
        public static readonly Assembly CommandsAssembly = typeof( RegistrationCommand ).Assembly;

        public static readonly IRegistration Commands =
            AllTypes.Of( typeof( ICommand<> ) )
                .FromAssembly( CommandsAssembly )
                .WithService.Select((t, b) => new List<Type> {t.FindMostSpecificChildInterfaceOf( b )} )
                .Unless( t => t.IsAbstract || t.IsInterface )
                .Configure( c => c.LifeStyle.Transient );
    }

Simple Component Registration Testing

Placing all of the registrations in a class like ComponentRegistrations greatly simplifies unit testing. I use a helper class that converts the single registration defined by AllTypes.Of(...) into individual registrations.

When testing registrations, you only need to test the “extra bits”.  In the above registration that equates to the .WithService.Select(...) bit.  The test looks like this:

    [Specification]
    public class When_registering_commands
    {
        private CompontentRegistrationsTestContext _context;

        public void Given(CompontentRegistrationsTestContext context)
        {
            _context = context;
        }

        public void When()
        {
            _context.WhenRegisteringWith( ComponentRegistrations.Commands );
        }

        [Then]
        public void the_service_should_be_defined_by_the_most_specific_interface_inheriting_from_ICommand()
        {
            _context.AllRegistrations(
                r => r.ServiceType.ShouldEqual(
                         r.Implementation.FindMostSpecificChildInterfaceOf( typeof(ICommand<>)) ) );
        }
    }

The context class that converts the registrations uses an IKernel stub to convert bulk registrations like BasedOnDescriptor into ComponentRegistration instances.

    public class CompontentRegistrationsTestContext
    {
        private List<ComponentRegistration> _registrations;

        public void WhenRegisteringWith( IRegistration registration )
        {
            _registrations = new List<ComponentRegistration>();

            var componentRegistration = registration as ComponentRegistration;
            if( componentRegistration != null )
            {
                // We want to capture the component registrations, not execute them
                _registrations.Add( componentRegistration );
                return;
            }

            // If they are not component registrations, they will be descriptors that
            // generate numerous registrations ( i.e. BasedOnDescriptor )
            var kernel = MockRepository.GenerateStub<IKernel>();
            kernel.Stub( stub => stub.Register( null ) )
                .IgnoreArguments()
                .Callback( new RegisterDelegate( CaptureRegistrations ) )
                .Return( kernel );

            registration.Register( kernel );
        }

        public void AllRegistrations( Action<ComponentRegistration> assertion )
        {
            _registrations.Do( assertion );
        }

        public bool ContainsRegistration( Func<ComponentRegistration, bool> matchCriteria )
        {
            return _registrations.Any( matchCriteria );
        }

        private delegate bool RegisterDelegate(IRegistration[] registrations);
        private bool CaptureRegistrations(IRegistration[] registrations)
        {
            _registrations.AddRange(registrations
                .Select(r => (ComponentRegistration)r));
            return true;
        }
    }

Simplify Complex Component Registrations

Where I need more complex registrations that need to work with the configuration, I write a custom IRegistration implementation. The following example registers a component to intercept and redirect emails being sent from the website.  Usign a custom registration means that I can add all of the configuration required by components to the facility configuration in the simplest possible form, yet still use parameters for configuring components.

    public class RedirectingEmailSenderRegistration : IRegistration
    {
        public const string RedirectingEmailSenderKey = "redirecting.emailsender";
        public const string RedirectConfigurationChildKey = "redirectEmails";
        public const string RedirectConfigurationToAddressKey = "to";
        public const string RedirectConfigurationSkipSendingKey = "skipSending";

        private readonly IConfiguration _configuration;

        public RedirectingEmailSenderRegistration( IConfiguration facilityConfiguration )
        {
            _configuration = facilityConfiguration.Children[RedirectConfigurationChildKey];
        }

        public void Register(IKernel kernel)
        {
            kernel.ConfigurationStore.AddComponentConfiguration(
                RedirectingEmailSenderKey,
                BuildRedirectingEmailSenderConfiguration() );
            kernel.AddComponent(
                RedirectingEmailSenderKey,
                typeof( IEmailSender ),
                typeof( RedirectingEmailSender ),
                LifestyleType.Singleton );
        }

        private IConfiguration BuildRedirectingEmailSenderConfiguration()
        {
            if( _configuration == null )
            {
                throw new ConfigurationErrorsException(
                    "Missing configuration for the redirecting email sender.  Please ensure the following element is present and correct: <redirectEmails to=\"redirect address here\" />" );
            }
            var redirectAddress = _configuration.Attributes[ RedirectConfigurationToAddressKey ];
            if( String.IsNullOrEmpty( redirectAddress ) )
            {
                throw new ConfigurationErrorsException(
                    "Missing configuration for the redirecting email address sender.  Please ensure the to attribute is populated with a valid email address" );
            }
            var skipSending = _configuration.Attributes[ RedirectConfigurationSkipSendingKey ];
            if( String.IsNullOrEmpty( skipSending ))
            {
                skipSending = Boolean.FalseString;
            }
            var configuration = new MutableConfiguration( "component" );
            configuration.Attribute( "id", RedirectingEmailSenderKey )
                .CreateChild( "parameters" )
                .AddChild( "redirectTo", redirectAddress )
                .AddChild( "skipSending", skipSending );

            return configuration;
        }
    }

An additional benefit of this is that you can inspect the result of the registration to ensure it works the way you expect it to.

    [Specification]
    public class When_registering_the_redirecting_email_sender
    {
        private RedirectingEmailSenderRegistration _registration;
        private IKernel _kernel;
        private IConfigurationStore _configurationStore;

        public void Given(DevelopmentContainerConfigurationContext context)
        {
            _registration = new RedirectingEmailSenderRegistration( context.BuildFacilityConfiguration() );

            _kernel = MockRepository.GenerateStub<IKernel>();
            _configurationStore = MockRepository.GenerateStub<IConfigurationStore>();

            _kernel.ConfigurationStore = _configurationStore;
        }

        public void When()
        {
            _registration.Register(_kernel);
        }

        [Then]
        public void the_redirecting_email_sender_is_configured()
        {
            _configurationStore.AssertWasCalled(
                cs => cs.AddComponentConfiguration( null, null ),
                c => c.IgnoreArguments()
                         .Constraints(
                         Is.Equal( RedirectingEmailSenderRegistration.RedirectingEmailSenderKey ),
                         Is.Anything() ) );
        }

        [Then]
        public void the_redirecting_email_sender_is_registered()
        {
            _kernel.AssertWasCalled(
                k => k.AddComponent(
                         RedirectingEmailSenderRegistration.RedirectingEmailSenderKey,
                         typeof( IEmailSender ),
                         typeof( RedirectingEmailSender ),
                         LifestyleType.Singleton) );
        }
    }

Simplify Management of Component Registrations

Generally when I am developing a web application, I have two sets of components that I need to manage, one set for production – the components that make up the actual application, and a second set for development that perform tasks like redirecting the email from the application into a specific email address.

Rather than having to remember which components belong to what set, I create two facilities to register the components, the first is <ApplicationName>ConfigurationFacility and the second is DevelopmentConfigurationFacility. Because all the registrations can be accessed via static members of the ComponentRegistrations class I can create a simple facility as shown below.  This means it is easy to see what components are being registered in the container and in what order ( you can also register facilities in the same way ):

    public class DevelopmentConfigurationFacility : AbstractFacility
    {
        protected override void Init()
        {
            Kernel.Register( DevelopmentComponentRegistrations.DatabaseController );
            Kernel.Register( DevelopmentComponentRegistrations.RedirectingEmailSender( FacilityConfig ) );
            Kernel.Register( DevelopmentComponentRegistrations.NHibernateProfilerInitialisingConfigurationBuilder );
            Kernel.Register( DevelopmentComponentRegistrations.EnableStatisticsPersistenceConfigurer );
            Kernel.Register( DevelopmentComponentRegistrations.ShowSqlPersistenceConfigurer );
        }
    }

By using facilities to group component registrations, I can effectively “bootstrap” the container into one of two modes ( development or production ) by adding or removing one facility registration ( instead of 5 component registrations + the associated component configuration ).

Careful thought about the strategies you use to manage and test your component registrations may cost you some time up front, but it is time well invested as once it is up and running, you should end up with a zero-friction environment wrt components.

If it just works and you don’t notice when it does – you’ve done it right

Showing commits not yet on master

August 27, 2009 Neal 3 comments

I use git most days now, it means I can work on my laptop and commit back to our subversion repository when I am connected again ( or when I finish working on the feature ).

As I have posted previously, I cannot dcommit multiple commits – git freaks out and makes a mess of things after the first commit. To get around this, I do all my work on a topic branch and then cherry-pick the commits from the topic branch into master and dcommit each one individually.  While this works, it is painful so I am slowly working out how to get the list of commits and cherry-pick then dcommit them individually by stringing a bunch of commands together.

The first thing I need to do is get a list of the commit hashes that need to be cherry-picked from the topic branch.


git checkout master
git log master..<topic_branch> --format="%h" > commits.txt

This gives me a nice list of commit hashes that I can use to issue the cherry-pick commands. Beware – at this point the list is in inverse commit order – that is, the oldest commits are at the bottom of the list.

I will keep updating this post as I get closer to having a single command that I can issue to mimic the following ( that I can use due to some weird error )

git checkout master
git svn rebase
git rebase <topic_branch>
git svn dcommit
git branch -D <topic_branch>

Update … with very little research and effort I have managed to create a bash script that mimics the workflow above.
The following bash script gets a list of the commits that are on the topic branch but not in the master in chronological order oldest first and replays them onto the master, one commit at a time, dcommitting the changes between each commit. Ironically, while I was researching / writing this script I may have found the solution to my issue – git svn dcommit --no-rebase.


#!/bin/bash
echo `git checkout master`
echo "Rebasing against remote svn repository"
echo `git svn rebase`
for commitHash in `git log master..$1 --reverse --format="%h"`
do
echo "Merging next commit"
echo `git cherry-pick $commitHash`
echo "Commiting changes to remote repository"
echo `git svn dcommit`
done
echo "$1 successfully merged and dcommitted - don't forget to delete the branch"
exit 0

The script can be put anywhere that is on the bash path – I currently leave it in the root of the folder I am working in ( same folder that houses the .git folder ). Calling the script is as simple as dcommit <topic_branch>.

Categories: Git

Fighting with git svn

August 25, 2009 Neal 1 comment

First up, a disclaimer – I am a git n00b therefore anything below may or may not be correct but “it works for me” so I am putting it out here for anyone else facing similar issues ( and also for future reference as I have a feeling this will happen a few more times yet ).

I have recently moved to using git on my laptop. Originally I installed GitExtensions ( which uses msysGit 1.6.3 ), but after some problems I uninstalled that and installed msysGit 1.6.4 using this excellent guide from Jason Meredith.

I cloned the repository I was working from using:

git svn clone https://<server>/svn/<projectname>/trunk

I didn’t need all of the branches so I only grabbed the trunk. My upstream repository is a subversion repository hosted within Visual SVN Server 2.05.  After cloning the subversion repository I wanted to work on, I started working as usual with the following workflow:


git checkout -b
... work work work ...
git commit -a -m ""
... more work / commit cycles ...

Once I had completed the task ( integrating the spark engine as it happens – what a joy to work with that is ), I jumped back to the master to commit my changes back to the upstream repository. I rebase the changes from my topic branch onto the master so that I end up with a linear commit history that doesn’t confuse git svn.


git checkout master
git svn rebase
git rebase
git svn dcommit

And this is where the trouble started. git svn completed the first commit of 4 and then decided there were no more changes between current head and refs/remotes/git-svn so it reset to the latest refs/remotes/git-svn and left me with a number of unstaged files that made up the changes for the remaining 3 commits. Poking around with git log showed me that git still had the commits in master but I could no longer dcommit them due to git and svn being out of sync.

To clean up git I reset master to the last committed svn revision and then removed all of the git commits after that using a combination of git svn reset -r , git reset –hard and git clean -f ( I can’t remember the exact sequence of commands so I won’t post them just yet ). Once I had both git and git svn synchronised back to the point of the last commit, I cherry picked each commit from the topic branch and dcommitted them one at a time to the remote subversion repository:


git checkout
# Use this to get the sha1 commit tags of the commits to cherry pick
git log
git checkout master
# Repeat the following for each commit on the topic branch that needs to be dcommitted
git cherry-pick
git dcommit

This is essentially the same as git rebase / git svn dcommit except you are pulling the commits one at a time.

While I still don’t understand why git svn dcommit refuses to work for multiple commits, at least I can continue using it to work offline, although I think I’ll be using git merge –squash going forward.

Categories: Git

Creating entities in unit tests

August 23, 2009 Neal 1 comment

An interesting question came up on twitter a moment ago about creating entities for unit tests, what follows is the approach that I use to enable me to create entities with the minimum possible code yet the maximum possible flexibility.

I have two entities Account and User, the code for them is shown below.


    public class Account : Entity<Account>
    {
        public Account( string accountName )
        {
            Name = accountName;
            Users = new List<User>();
            Questionnaires = new List<Questionnaire>();
        }

// ReSharper disable UnusedMember.Local
        private Account()
        {
            // Required by NHibernate
        }
// ReSharper restore UnusedMember.Local

        public string Name { get; private set; }
        public User Owner { get; private set; }
        public IList<User> Users { get; private set; }
        public IList<Questionnaire> Questionnaires { get; private set; }

        public User CreateUser( string username, string passphrase, string name, string emailAddress, string country, string timezone, bool asOwner )
        {
            var user = new User( username, passphrase, name, emailAddress, country, timezone, this );
            Users.Add( user );
            if( asOwner )
            {
                Owner = user;
            }

            return user;
        }

        public Questionnaire CreateQuestionnaire( string name )
        {
            Contract.Requires( () => name );
            var questionnare = new Questionnaire( name, this );
            Questionnaires.Add( questionnare );
            return questionnare;
        }
    }

    public class User : Entity<User>
    {
        public const int MaxAuthenticationRetryCount = 5;

        public User( string username, string passphrase, string name, string emailAddress, string country, string timezone, Account account )
        {
            Contract.Requires( () => username );
            Contract.Requires( () => passphrase );
            Contract.Requires( () => name );
            Contract.Requires( () => emailAddress );
            Contract.Requires( () => country );
            Contract.Requires( () => timezone );
            Contract.Requires( () => account );
            Username = username;
            Passphrase = passphrase;
            Name = name;
            EmailAddress = emailAddress;
            Country = country;
            Timezone = timezone;
            Account = account;
            EmailAddressConfirmed = false;
        }

// ReSharper disable UnusedMember.Local
        private User()
        {
            // Required by NHibernate
        }
// ReSharper restore UnusedMember.Local

        public string Username { get; private set; }
        public string Passphrase { get; private set; }
        public string Name { get; private set; }
        public string EmailAddress { get; private set; }
        public string Country { get; private set; }
        public string Timezone { get; private set; }
        public Account Account { get; private set; }
        public bool EmailAddressConfirmed { get; private set; }
        public int AuthenticationRetryCount { get; private set; }

        public void ConfirmEmailAddress()
        {
            EmailAddressConfirmed = true;
        }

        public bool Authenticate( string passphrase )
        {
            Contract.Requires( () => passphrase );
            if (IsAccountLocked())
            {
                return false;
            }

            var isAuthenticated = String.Compare( Passphrase, passphrase, StringComparison.InvariantCulture ) == 0;
            if (isAuthenticated)
            {
                AuthenticationRetryCount = 0;
            }
            else
            {
                AuthenticationRetryCount += 1;
            }

            return isAuthenticated;
        }

        public bool IsAccountLocked()
        {
            return AuthenticationRetryCount >= MaxAuthenticationRetryCount;
        }

        public void ResetPassphrase( string newPassphrase )
        {
            Contract.Requires( () => newPassphrase );
            Passphrase = newPassphrase;
        }

        public void UnlockAccount()
        {
            AuthenticationRetryCount = 0;
        }
    }

To manage creation of these entities during testing I have a static factory class for each that manages creating the entities and optionally populating any properties ( often using reflection ). The source for these is as follows:

    public static class AccountFactory
    {
        public static Account Create()
        {
            var account = new Account( "Account Name" );
            UserFactory.Create( account, true );
            return account;
        }
    }

    public static class UserFactory
    {
        public static User Create()
        {
            var account = AccountFactory.Create();
            return Create( account, true );
        }

        public static User Create( Account account, bool asOwner )
        {
            var user = account.CreateUser( "Username", "a valid passphrase", "Name", "email@address.com", "New Zealand", "GMT+12", asOwner );
            return user;
        }

        public static User WithUsername( this User user, string username )
        {
            user.SetPropertyValue( u => u.Username, username );
            return user;
        }

        public static User WithPassphrase( this User user, string passphrase )
        {
            user.SetPropertyValue( u => u.Passphrase, passphrase );
            return user;
        }

        public static User WithEmailAddress( this User user, string emailAddress )
        {
            user.SetPropertyValue( u => u.EmailAddress, emailAddress );
            return user;
        }

        public static User MimicFailedAuthenticationAttempts( this User user, int failedAttempts )
        {
            user.SetPropertyValue( u => u.AuthenticationRetryCount, failedAttempts );
            return user;
        }

        public static User MimicLockout( this User user)
        {
            user.SetPropertyValue( u => u.AuthenticationRetryCount, User.MaxAuthenticationRetryCount );
            return user;
        }
    }

The create methods return a valid entity initialised with a default set of values that can be used for testing any scenario you like. If you need to customise the data in the entities to fit a specific test scenario, the extension methods allow additional tweaking of the entity data ( often via reflection ).

This approach allows me to build entities quickly for testing purposes while ensuring that I don’t have to maintain a God class that manages building many different entities and their relationships, it is essentially convention over configuration for my entities.

Categories: Unit Testing, c#

A new approach to agile

August 18, 2009 Neal Leave a comment

I’m tired of hearing and reading about organisations that are “agile” when I know they aren’t.  Agile is the trendy new (old) thing, and as Janusz Gorycki points out so well in his post titled Agile is Dead, the main reason we have AINO ( agile in name only ) is PHBs.

I’m propose we create a new agile methodology, one that takes from scrum and xp and lean and provides a loose framework of guidelines designed to be used by competent professionals rather than talked about by PHBs and certificate hungry consultants.

To ensure managers don’t want to be known for having implemented this new methodology, I propose we call it

“Getting Shit Done”

How many PHBs want to front up to their bosses and explain they need to spend money on “getting shit done” – it’s what they are paid to do anyway, isn’t it?

To drive away the money grubbing courseware consultants, the methodology should be simple and the first rule of this new methodology should be:

You can’t teach getting shit done, you can only learn it

Now if it were only as simple to do as it is to write :(

Categories: General