Friday, 12 November 2010

Using a Guid as a version column in NHibernate

One of the great features of NHibernate is the almost infinite control it gives you over mapping to existing database structures with its custom type mapping. Turns out custom types can also be applied to version columns for managing concurrency. Thanks to Justice for the pointer on my stackoverflow post :)

The basic method is to simply implement a NHibernate.UserTypes.IUserVersionType and implement the Seed and Next methods to return Guids. The rest is just Guid type mapping.

The custom type can then be registered in FluentNHibernate using this code:

   1:  public AnimalMap()
   2:  {                       
   3:      Id(x => x.Id);    
   4:      Map(x => x.SpeciesId);
   5:      Version(x => x.ConcurrencyId).CustomType(typeof(GuidVersionType));
   6:      Map(x => x.Name);    
   7:      Map(x => x.NumberOfLegs); 
   8:  }

The full code is below:

   1:  class GuidVersionType : NHibernate.UserTypes.IUserVersionType
   2:  {
   3:      public SqlType[] SqlTypes
   4:      {
   5:          get
   6:          {                
   7:              var types = new SqlType[1];
   8:              types[0] = new SqlType(DbType.Guid);
   9:              return types;
  10:          }
  11:      }
  13:      public System.Type ReturnedType
  14:      {
  15:          get { return typeof(Guid); }
  16:      }
  18:      public new bool Equals(object x, object y)
  19:      {
  20:          if (x == null)
  21:          {
  22:              return false;
  23:          }
  25:          return x.Equals(y);
  26:      }
  28:      public int GetHashCode(object x)
  29:      {
  30:          return x.GetHashCode();
  31:      }
  33:      public object NullSafeGet(IDataReader rs, string[] names, object owner)
  34:      {
  35:          var value = NHibernateUtil.Guid.NullSafeGet(rs, names[0]); 
  36:          if (value == null)
  37:              return null;
  39:          return (Guid) value;
  40:      }
  42:      public void NullSafeSet(IDbCommand cmd, object value, int index)
  43:      {
  44:          if (value == null)
  45:          {
  46:              NHibernateUtil.Guid.NullSafeSet(cmd, null, index);
  47:              return;
  48:          }           
  49:          NHibernateUtil.Guid.NullSafeSet(cmd, value, index);
  50:      }
  52:      public object DeepCopy(object value)
  53:      {
  54:          if (value == null) return null;
  55:          var copy = ((Guid) value);
  56:          return copy;
  57:      }
  59:      public bool IsMutable
  60:      {
  61:          get { return false; }
  62:      }
  64:      public object Replace(object original, object target, object owner)
  65:      {
  66:          return original;
  67:      }
  69:      public object Assemble(object cached, object owner)
  70:      {
  71:          return cached;
  72:      }
  74:      public object Disassemble(object value)
  75:      {
  76:          return value;
  77:      }
  79:      public int Compare(object x, object y)
  80:      {
  81:          return ((Guid) x).CompareTo((Guid) y);
  82:      }
  84:      public object Seed(ISessionImplementor session)
  85:      {
  86:          return Guid.NewGuid();
  87:      }
  89:      public object Next(object current, ISessionImplementor session)
  90:      {
  91:          return Guid.NewGuid();
  92:      }
  93:  }

This works in FluentNHibernate 1.1.

Wednesday, 20 October 2010

Setting the Hudson/Jenkins next build number programatically

Programatically setting the next build number in Hudson/Jenkins is a useful thing to do if you have a build pipeline. After a bit of research it seems there are 3 main approaches that could be useful in different situations:

  1. Set the nextBuildNumber.txt in your Hudson job's directory
  2. Use environment variables for build number passthrough (see @ruby_gem's post here)
  3. Use the nextBuildNumber Hudson plugin and HTTP POST the build number to it

In this post I'll be looking at option 3 - using the nextBuildNumber Hudson plugin.

Using the nextBuildNumber Hudson plugin

Firstly install the nextBuildNumber plugin. You can now set the next build number for a job manually from the plugin link that appear on the left.
To use this programatically you simulate the manual for submission with a web client. I tested it with FireFox ReST client.
To set the next build number to 999 simply formulate an HTTP POST to your Hudson URL:

e.g. http://myhudsonserver:8080/job/myhudsonjobname/nextbuildnumber/submit
With the form data
And the HTTP Content-Type request header
Content-Type: application/x-www-form-urlencoded

If your Hudson is secured you'll need to authenticate your web client too.

That's it! Finally it's worth noting that build numbers in Hudson can only go up!

Thursday, 16 September 2010

Error Handling CI Deployments Using Powershell

PowerShell's a great tool for use in remote deployments from a CI server. However, it's default error handling does not cause a failure on error which can leave failed deployments reporting success!

To make PowerShell scripts fail on non-terminating errors add the following line to the top of the script after any params:

$ErrorActionPreference = "Stop"
This will cause the script to fail on terminating and non-terminating errors hence preventing the Powershell script succeeding when elements of it have failed.

Thursday, 26 August 2010

Better TDD By Writing Your Asserts First

Writing unit tests with an Arrange, Act, Assert structure definitely helps but the order often seems at odds with the mental process of TDD. Best practice is to write your asserts first. Here's why:

Arrange First?

Arrange-ing first is virtually impossible. You have no idea what to Arrange until you've written the Act or Assert. This is particularly important when Mocking/Stubbing as the Arrange requires knowledge of the implementation which is exactly what you don't have at this point! * see below

Act First?

Act-ing first seems more reasonable but requires something to first be arranged which can lead you down the dark path of arranging first. If there's any uncertainty about the purpose of the test, which there often is, then this can result in wasted effort.

Assert First

Assert-ing first forces you to clarify the purpose of your test early. Have you ever had that paired conversation of "What are we really trying to do here?", well asserting first is having that conversation. Sure you may not be able to write the entire assert standalone but it will help you to drive the rest of the test and implementation with a clearer mind.

* but I do have knowledge of the implementation

Really? For a trivial implementation great! But if you have an existing external dependency then how do you know that this implementation should call it directly? You don't! Sure it will eventually get called but that may not be the concern of the class under test. Switch back to top down design and let the Assert drive out the interface you require the external dependency to have. Then, and only then, either wrap the dependency to make it expose the interface you require or take the well considered decision to use it directly.

Assert first is really helpful for all but the most trivial tests and can help you achieve that holy grail of loosely coupled, highly cohesive code. Try and see if it works for you!

Breaking The Legacy Bind : A Tale Of Build Automation

I've recently moved teams and following a brief honeymoon on a greenfield web app we're now swimming in the murky waters of the "Legacy Codebase". Imagine a world with no continuous integration, patchy test coverage, untamed dependencies, COM+, a long manual build and deployment process and to top it all off, Visual Source Safe.
If this doesn't make you shudder then best stop reading now :)

Granted, there are probably many worse legacies out there and much of our underlying code is good but it's still a significant departure from the instant builds and frequent releases we had been making.

Science Friction

The initial obstacle faced here is friction in the development process. Friction resulting mainly from the repetitive manual build process. The manual build takes time; lengthening the feedback cycle. It's also tedious and error prone. These two facts alone can prevent even the most diligent of developers from making the refactorings necessary to keep the codebase in good health. Our first job - automate.

Automation, Automation, Automation

Automating the build process to run on check-in removes the tedium of doing it manually and is relatively easy to do with any CI server. Fortunately our code already has a well organised suite of NAnt scripts so we simply configured Hudson, our CI server, to run them and display the test output. A relatively quick win.

If you're not so lucky you could start with automating one part at a time. Just note down your manual process and automate each step in turn.

Migration From VSS To TFS

Using Hudson mandated the source code be migrated from Visual Source Safe to a system more suitable for use with a CI server - in our case Team Foundation Server. The migration itself is fairly straightforward with the Microsoft migration tool and instructions but can be time consuming so plan carefully, especially if your VSS repository is in constant use.

I've previously done this from VSS to SVN and there are probably tools out there to move between most source control systems, but beware, not all features are supported by all systems e.g. VSS pinning, SVN externals. Of course, if you're not concerned about the history, tags etc. you can always just check-in a fresh copy from your old source control to the new one and get going straight away.

Verify The Build

The first build is by far the biggest risk and taking the time to verify it is very worthwhile if you care about the quality of your software. This cost us a couple of days due to build/env issues but it's either that or the entire thing is a no-go so don't be tempted to scrimp here!

Comparison tools such as WinMerge and BeyondCompare can help here to compare the checkouts from each source tree or even build artefacts.

Building For The Future

We're not done here! An automated build is a huge leap forward and allows you to concentrate on skilled activities that deliver more value but it's by no means the end.

Build time is important and reducing it is next on our hitlist. Time spent waiting for a build is often time wasted or forces you into the undesirable world of multitasking. If your build takes longer than it does for you to make a cup of tea then there may well be room for improvement.

Final Thoughts

Dealing with unfamiliar or hard to work with code can be daunting. In my (limited) experience it's all about confidence - get stuck in, and little by little you'll find a path forwards. If you're struggling then I'd highly recommend Michael Feathers' Working Effectively With Legacy Code (ISBN 0131177052) for some inspiration.

Friday, 9 July 2010

Barcamp Blackpool 2010

There's been a US and UK election since my last post but it's time to saddle up and ride this ol' blog horse once more. Besides, this event really does deserve a mention.

Q: What do you get when you take several hundred sticks of rock, a wizard, 120 technology people, a pieman, a sprinkling of speakers, a free bar and leave them all in a casino ballroom for a day?

A: Barcamp Blackpool (@bcblackpool)

For anyone who's not attended such an event before it's a free developer and technology unconference.

Unconference!? What's that?

Talks are arranged on the day, simply turn up with one and stick a post-it with your talk name in one of the available slots. Delightfully low tech and the ensuing speaker scrumdown is a marvellous spectacle. Only the strongest survive. If Attenborough made people documentaries ...

Once talks are posted you're then free, after a quick ice-breaker, to browse the line-up and drop in on anything that takes your fancy.

Talk, Talk, Talk

Talks covered a variety of subjects both technical and non-technical subjects from British Sign Language to jQuery to Ferret Keeping although it's fair to say the majority of talks have an IT bias.

Excepting the free pie for lunch notable highlights included sessions on 45 Second Elevator Pitches, IT Recruitment (by a recruiter and nice chap I should say), Sociograms (that's connections between groups to you and me), IT Education and more.

Educational part over it's on to evening entertainment including free food, free bar and magic show before a careless plunge into the murky depths of Blackpool proper. Did I mention there's some free stuff?

A special mention is also deserving of the organiser, and my pink haired ferret-loving @esendex colleague Gemma Cameron (@ruby_gem) whose tireless enthusiasm, merry band of helpers and fondness of wine made the event hugely entertaining.!

The Rollercoaster Of Barcamp Love

  • The Big One @ Blackpool Pleasure Beach
  • Inspirational Speakers
  • My first, and I suspect last ever, game of Werewolf*
  • Karaoke Fun Bar - Blackpool's 8-Mile styled rap dungeon complete with MCs
  • Pies
  • Squirty Gertie
  • Exchanging Ideas

* When Barcamp became Band-Camp. Ask @neilkilbride for his cup truly overfloweth.

Barcamp comes to Nottingham

Celebrate! Barcamp is coming to Nottingham. Join the discussion at the Google Group here.