Maritime User Group Tour '08 Wrapup

Last night I finished up my final presentation on a tour of the Maritime User Groups.  This was the first time that I'd been out to the Maritimes and I had a blast during the whole trip.  Unfortunately, the need for travel from one town to the next pretty much meant I wasn't getting to see anything along the way.  Luckily the Nova Scotia-New Brunswick leg of the trip was done via car and I was able to see some of the landscapes during the trip.

I started out in St. John's Newfoundland at the St. John's User Group and fololwed that up with stops in Halifax Nova Scotia at the DevEast group, Moncton New Brunswick at the DevEast group and lastly the Fredericton .NET User Group in Fredericton New Brunswick.  In all places I met passionate, practical developers who are looking to do the best that they can to grow and deliver software.

For those that attended and would like the slide deck, it can be downloaded here.

Thanks to Derek Hatchard for setting up the tour and the UG leads (Derek, Amanda Murphy, Jason Row and Daniel Crenna) for having me at their groups.  If you're in the Atlantic provinces of Canada and are a developer, these are the people that are driving your community forward.

Fall events

It seems that every spring and fall the developer world seems to ramp up and developers around the world flock to conferences and user group events.  For me this usually means I'm out and about for the better part of 2 months straight.  If you're interested, here's my schedule for the next couple of months.  Some I'm speaking at (presentations listed) and others I'm just an attendee.  Either way, if you're going to be around at any of these events shoot me a note and we'll hook up for a drink and conversation.

October

16th @ 7pm in Victoria BC -- Victoria .NET Developer Association -- ORM Fundamentals 

20th in St. John's Nfld -- St. John's .NET User Group -- TBD

21st in Halifax NS -- DevEast -- The Big OO

22nd in Moncton NB -- DevEast -- The Big OO

23rd @ 7pm in Fredericton NB -- Fredericton .NET User Group -- The Big OO

30-31 in Austin TX -- KaizenConf

November

10-14 in Barcelona -- TechEd EMEA

December

1-5 in Montreal PQ -- DevTeach -- ORM Fundamentals, Refactoring to Logical Layers, Fluent Interfaces

Anonymous Access to SVN Repository for IglooCommons

I've had a problem with the anonymous access settings for my VisualSVN installation that is hosting IglooCommons.  It just didn't work without prompting for credentials.  Understandably, no one seemed to care until the other day when Sebastijan shot me an email claiming that he wanted to take IglooCommons for a spin.  Interestingly, Rob posted a fix for my problem on the same day, saving me the pain of having to figure shit out on my own.

So now, IglooCommons has been released to the masses!  I expect the race to download to be tantamount to a snail race!

Recruiting firms

My past experience with recruiters has been at a level that I put on par with my recent experiences with newbies to my team.  Today I got this from a guy I know who just changed jobs through a new recruiting firm.

Recruiting Firm X is smart.  They sent me a giant gift basket to my job.. one branded coffee metal big mug thinger.. two glasses and a bottle of wine.. total cost probably not very high.. but it got noticed by my co-workers and more importantly the coffee mug has their name in a fairly noticeable fashion on it.

He's right.  It is a great advertising move on their part.  Especially if they had it sent to the front desk.  Inevitably the overworked, under appreciated receptionist had it sit there for an hour or more.  That whole time people came and went and saw the recruiting firms colours and name.  Once the receptionist found the time, the basket had to be packed through the office, past a bunch of prying cubical gophers who wanted to know one thing only: who got the pressie?  By the time that basket reached my friends desk, the recruiting firm had generated a great deal of buzz...which is exactly what advertising is meant to do.

What I like the most about this is that they sent booze to the work place.  It's almost a free ticket to get drunk (or keep your morning vodka and Cheerio buzz going) at work.  This guy was talking about how great a marketing idea it is that the recruiting firms name is on the coffee mug when he walks around the cubicle maze during the day.  I say, what a great marketing ploy to have a developer walking around the cube maze all day with a glass of wine in his hand!  Who doesn't want to be associated with a group that empowers you in that way.

Anyways...I had to get a positive story about recruiters out there on the web.  There's more than enough bad ones, let's not forget that there might be one good one...is Agile Recruiting in Calgary it?  I dunno, but I like the booze part of them already.

Starting projects

I had an experience today that made me...well...flat out fucking angry.  When you start working with a new team, on a new project, at a new company...heck whenever someone can point at you and call you the "new guy", you need to be very careful with your desire to impose your belief system onto the group.  The only time that this is acceptable is if you've been brought in to impose change, but even then you usually will want to wade, not dive, into the pool.

Today I had to work with a relatively new-to-our-team person.  The previous work that this individual had been doing was being raved about.  I believed it.  Last week was my first time dealing with this individual and the experience was mixed.  I don't mind a good throw down verbal argument about different ideas.  I certainly don't back down from them if I am passionate about the topic.  We had one last week.  The topics is irrelevant, but I was disappointed when he simply walked away from it after making his point, but not defending it when I challenged it.  Maybe it triggered some kind of carnal notification of weakness because today I had the need to get aggressive with him and I went after him like he was the falling behind, sickly gazelle you see the hyena grabbing on Animal Planet.

There are some things that get me excited.  Some get my hairs to stand on end.  Others, well, they just make me flat out mad.  One thing you never do is spend 2 days on a successful project and then declare that it's practices are incorrect *unless* the practice in question is impeding the project's ability to improve on it's current state.  This individual today declared that an automated build script was a waste of time, that he wasn't going to maintain it and the fact that his most recent checkins breaking the CI server weren't his problem.  Like I said, there are some things that just make me mad.  By this time all the buttons were pushed and I was in full hunt mode.

The things that he was fighting for were fundamental practices that many of us won't do without anymore.  Automated build scripts, Continuous Integration, checking in code that isn't broken, having succeeding tests.  All of his arguments for why we needed to remove this standards from our project boiled down to him not wanting to change his ways.  The F5 compile and one assembly per csproj file was the only possible way to do things.  These are practices that I hold near and dear since they have helped me to significantly improve the delivery of every project I have used them on.  So that made me mad.  But I turned irate when any challenge to his belief system was met with either silence or "This is what VS is for".  If you're going to show up at a gun fight, you'd better be willing to shoot bullets, not blanks.  Simply having cartridges ejecting from the rifle doesn't mean that you're in the fight.

The thing that really set me over the edge was when I was told "I'm really surprised by you."  When I asked him to elaborate (in my own special profane way) he wouldn't.  If you're going to get me mad and then call me out, please step up to the plate with a set of fucking balls.

Since ending the call the thing that has fueled the anger more is that I just spent four days training on these things and this guy was in the room.  It's obvious that he didn't pay any attention.  Note to never have internet access in a training room again.

Anyways, nothing good came of it other than the fact I reverted back 3 checkins that this guy had made and told him to spend the weekend learning nAnt and TortoiseSVN since we weren't changing what was already working.  I'm pretty sure that Tom is regretting leaving work 30 minutes too early now too.

That should be enough venting for one day.  Thank god it's the weekend....and that I have a good scotch.

Bricks and Sponges

I had a conversation the other day with Tom Opgenorth about the trends you see when you're ending a contract with a client.  Our experiences both show that during the life of a project the client will usually (painting with broad strokes here) talk like they want to learn, understand and be competent with the project.  Most claim that they want to grow that knowledge during the life of the project so that, at the time of your departure, they will have the ability to smoothly transition the work.  Rarely does this seem to happen. Instead, the end of your tenure on the project comes and the client scrambles to ensure that some knowledge is transferred so that they have the minimum level necessary to start getting up to speed.  It's always a mad scramble and the client is left with a huge disruption in the project as a result.

This is where bricks and sponges comes in.  It seems that the client (or the employer if you're an employee on a team...it happens their too in our experiences) is a brick while they're on the project.  They're porous and quite capable of absorbing, but for some reason they also repel the knowledge they need to absorb.  When it comes time to transition off of the project, the client all of a sudden transforms in to a sponge and tries to saturate themselves as quickly as possible.  While the metaphor doesn't work a hundred percent, it does fit fairly well.

I've not seen one project successfully transition with minimal knowledge disruption when a team member departs.  I think it's one of the major problems that we have, especially if we're working as consultants.  We have to find better ways to make our clients sponges through the entire life of the project so that we can pour the water to them gently instead of from a fire hose.  Some of that responsibility does rest with the client though, and there's not a lot that we can do to mitigate active unwillingness to constantly transfer knowledge on their parts.  If they don't have the desire or the correct motivations to learn during the project's live, all we can do is keep pouring the knowledge to them and let them do with it what they choose.

I know some of you are thinking that knowledge transfer problems can be mitigated by creating a lot of documentation or transition papers.  I say that it doesn't work.  Every time I've arrived onto a project that has claimed to have these documents, they have been woefully inadequate.  Worse yet, many were flat out incorrect.  Writing transition knowledge into a persistent state means that you have to continually update it to ensure that it's current state is correct.  Development teams are not prone to doing such tasks if they don't see any immediate, or very near, benefit from it.  That would indicate that writing transition documents at the last possible moment would be something that a developer would be willing to do, and that's true.  But leaving the creation of this type of document until the last moment is like trying to write a book about your project during the two week period between when you've given your notice and you depart.  There just isn't the time to do justice to all of the information that will need to be collected, organized and transcribed.

The only answer that I have for this is pushing the client to actively participate along the way.  Don't just say "We're using nAnt to do our build scripts."  Say that plus put the responsibility for changing, maintaining and enhancing the build scripts into their hands very early on.  This allows you to mentor them through the process of learning and absorbing the information that they will need to succeed in your absence.  If they consistently push back at you that you should be doing it all since you know it best, you have to push back.  If they can't see why you're forcing the learning experience on them, then you have to leave them to their own devices when the time comes.  You can't bear much responsibility for the success, or failure, of a project after you have left it.  All you can do is work hard to set it up to succeed when that time comes.

Class naming

In the process of writing one of the chapters in the brownfield book, I started thinking about class naming.  Some time ago I remember hearing someone saying that they didn't much like the use of class names that ended in 'er' even if they conveyed good intent.  For example:

SpellChecker

or

NameParser

My understanding is that the dislike stemmed from the thought that the use of 'er' made the name of the class to much like a verb, and that verbs were the domain of a method name.  I bought into it when I first heard this.  Now I'm not so sure.  In some cases I fully agree.  Other times I find it a little restrictive.  At times I'd change the name of SpellChecker to SpellCheckingService, and NameParser to NameParsingService.  No more 'er' ending, but it does start to encroach on another naming guideline that I have: don't use pattern names in class names.

In the end we want the class names to be intention revealing.  More-so the combination of class and method name should be intention revealing.  What do you people do in these situations?

NHibernate on WCF

I know that there are a few blog posts out there on this subject, so I feel like I'm repeating myself while writing this.  Bear with me...please.  Over the last month I've been chasing an ISession corruption error in our application with little success.  During that time I spent a lot of time looking at our WCF implementation to ensure that it wasn't some piece of that which was causing the problem.  Needless to say, it wasn't, but I have a much greater appreciation for the extensibility of WCF as a result.  Part of my research/debugging/hacking around/crying was looking into the most appropriate way to create, persist and end a nHibernate ISession object during each individual WCF OperationContract call.  Here's what I figured out and created.

The first, and easiest thing that you need to do is set the ServiceContract Attribute to have an InstanceContextMode =  InstanceContextMode.PerCall.  The key here is that I want per call isolation.  Choosing thie InstanceContextMode will force the creation of a new service context for each client request and ultimately create a new InstanceContext object for each call.  What you're doing here is telling WCF that every call to an OperationContext should be treated as a distinctly separate code execution area.  If you were to leave InstanceContextMode to its default (InstanceContextMode.PerSession) the execution area of the code would create an InstanceContext for the duration of the Channel's life. Basically, that would mean that creating a connection to the WCF service would create a new InstanceContext and all OperationContracts would have access to it until the channel was released.  This will allow you to access items in the InstanceContext across calls, which is not how we want to handle our ISessions.

[ServiceContract]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
[NHibernateContext]
public interface ICustomerServices
{
    [OperationContract]
    IEnumerable<CustomerListingDto> RetrieveListingOfAll();
}

So we've created a service that is set to have PerCall InstanceContexts.  This is the first step to creating and storing the ISession.  Putting an ISession into the InstanceContext requires us to create a custom extension using IExtension<T>.  All our extension needs to do is provide a place to store the ISession object for that OperationContract call.  The extensions on the InstanceContext have a lifetime that lasts only for the duration of the call.  In the end the extension looks like this:

public class NHibernateContextExension : IExtension<InstanceContext>
{
    public NHibernateContextExension(ISession session)
    {
        Session = session;
    }

    public ISession Session { get; private set; }

    public void Attach(InstanceContext owner)
    {}

    public void Detach(InstanceContext owner)
    {}
}

Now that we have that extension we need to get it attached to each and every OperationContract call that is handled by our service.  An IInstanceContextInitializer implementing class is used to trigger the addition of the extension to the InstanceContext.  Every time that an InstanceContext is initialized (which will be on every Operation call since we're using InstanceContextMode.PerSession) the NHibernateContextExtension is added to the newly created InstanceContext.  Also note that it is at this point that the NHibernate ISession object is created and assigned to the InstanceContext's extension.  It's here that the nHibernate session per operation call concept is implemented.

public class NHibernateContextInitializer : IInstanceContextInitializer
{
    public void Initialize(InstanceContext instanceContext, Message message)
    {
        instanceContext.Extensions.Add(
            new NHibernateContextExtension(
                NHibernateFactory.OpenSession()
                )
            );
    }
}

You probably noticed in the NHibernateContextInitializer class above that the ISession object is being created from a NHibernateFactory object.  This object is a wrapper for the native NHibernate ISessionFactory object.  We need it implemented in this way so that we have a technique for accessing a session factory that is created outside of the scope of this little framework.  Later in this post you will see how this object is used and initialized with a valid SessionFactory object.

public static class NHibernateFactory
{
    private static ISessionFactory _sessionFactory;

    public static void Initialize()
    {
        Initialize(new Configuration().Configure().BuildSessionFactory());
    }

    public static void Initialize(ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;
    }

    public static ISession OpenSession()
    {
        return _sessionFactory.OpenSession();
    }
}

With a way to attach a new ISession to every InstanceContext that is created, we need to trigger this process on each and every call.  To do that we will attribute the WCF service with a custom attribute.  All we need to do is create a class that is an Attribute and implements the IContractBehavior interface.  During ApplyDispatchBehavior we add an NHibernateContextIntializer to start the entire process of creating the new NHibernate ISession for each call.

public class NHibernateContextAttribute : Attribute, IContractBehavior
{
    public ISessionFactory SessionFactory { private get; set; }

    public void Validate(ContractDescription contractDescription, 
                            ServiceEndpoint endpoint)
    {}

    public void ApplyDispatchBehavior(ContractDescription contractDescription, 
                            ServiceEndpoint endpoint, 
                            DispatchRuntime dispatchRuntime)
    {
        dispatchRuntime.InstanceContextInitializers.Add(
            new NHibernateContextInitializer());
    }

    public void ApplyClientBehavior(ContractDescription contractDescription, 
                            ServiceEndpoint endpoint, 
                            ClientRuntime clientRuntime)
    {}

    public void AddBindingParameters(ContractDescription contractDescription, 
                            ServiceEndpoint endpoint, 
                            BindingParameterCollection bindingParameters)
    {}

Simply creating a new ISession for each call to the WCF service isn't enough.  We need to be able to work with that ISession object in our data access endeavours. To do that I've created a simple class with a static method on it that retrieves the NHibernateContext Extension from the current InstanceContext.  This is possible because there is only one InstanceContext during the life of each service call.  To make this fall in line with other 'Context' object that we are used to working with (like HttpContext) I've created the static method called Current.

public class NHibernateContext
{
    public static NHibernateContextExension Current()
    {
        return OperationContext.Current.
                InstanceContext.Extensions.
                Find<NHibernateContextExension>();
    }
}

All of that explanation is well and good, but the real trick is how the hell do you use this.  That is fairly simple.  You need to do three things. First you need to create and initialize a nHibernate SessionFactory and inject it into the custom wrapper that is provided in this code.  Normally you would want to do this once for the life of the application as shown by placing this code in the Application_Start of the global.asax file.  This code snippet shows two options for initializing the factory. The first line will automatically load a nHibernate SessionFactory using the hibernate.cfg.xml file that is in the same folder as the IglooCoder.Commons.dll file.  The second line allows more flexibility to initialize a nHibernate SessionFactory in the way that you need or want.

protected void Application_Start(object sender, EventArgs e)
{
    NHibernateFactory.Initialize();
    //or//
    NHibernateFactory.Initialize(new Configuration().Configure().BuildSessionFactory());
}

Second you need to attribute any services with the NHibernateContextAttribute) that will need to access data using nHibernate.

[ServiceContract]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
[NHibernateContext]
public interface ICustomerServices
{
    [OperationContract]
    IEnumerable<CustomerListingDto> RetrieveListingOfAll();
}

The final step is to make use of the ISession object that the framework is creating for each call.  As you can see in the code below there is a bit of a trick to using t

public abstract class BaseRepository<T> : IRepository<T>
{
    public T FetchById(int id)
    {
        return NHibernateContext.Current().Session.Get<T>(id);
    }
}

If you want to use this code and not have to write it all out you can grab the source from the project's Subversion trunk (https://igloocoder.net:8445/svn/IglooCommons/trunk/).  Compile the code running b.bat at the command line and you will find the compiled assemblies in the \compile folder.

My next post will talk about how to maintain testability while using this stuff.

Ideas for implementing this came from Dan Rigsby's posts on WCF extension here and here.

Announcing the ALT.NET Canada Conference

For the last half a year a group of us (Bil, James, Dave, Terry, Justice, Greg and Kyle) have been organizing the first ALT.NET conference in Canada and today, on Canada Day no less, we are announcing the opening of registration to it.  The event will happen on August 15-17 in Calgary. 

If you've not been to, or heard about, the ALT.NET conferences in Austin and Seattle, they have drawn many software development luminaries and created great conversations.  There are no predefined sessions like you would normally find at a conference.  The format follows the Open Spaces principle and is completely self organizing.  The topics, conveners and session attendees happen based on the needs of the day, hour or minute.  One of the most fantastic things about the conference is that conversations don't stop after an hour.  They will carry on in the halls, cab rides, restaurants, and most definitely in hotel lounges.

You can sign up here (http://www.altnetconfcanada.com/registration/index.castle) and review the current attendee list here (http://www.altnetconfcanada.com/participant/index.castle).  Note that the conference is capped at 100 registrants, so signup fast.  If you don't get into that list, sign up anyways to ensure that you're on the waitlist when people start cancelling.

Big shout out to the sponsors that we have so far: Thoughtworks, Solidhouse, CodeBetter and MSDN Canada.

I personally guarantee that one of the two Canadian delicacies you see here will be available in abundance at your hotel breakfast during the conference.  You'll just have to wait to see which one.

On this great day...

The majority of Canadians will be celebrating Canada Day and the creation of our country.  Lost on the majority of the population is that July 1st also marks a day of great sacrifice.  On this day in 1916 eight hundred and one of the Royal Newfoundland Regiment went over the top at Beaumont-Hamel.  The following following morning only sixty-nine answered the regimental roll call.  Since 1916 Newfoundland has born the weight of this sacrifice on their own.  Since 1949 it has been the responsibility of Canadians to remember these men as some of the great fathers of our country.  While they are the brunt of many jokes, Newfoundlanders have a resilience that is characterized by the fact over one percent of it's youth left their homes, country and continent to fight in WWI and sacrifice their lives or their health.

While we celebrate Canada's birthday and the many things we have to be thankful for, we cannot forget to stop and thank the strong, the brave and the selfless who have helped...even if they weren't Canadians at the time.

"It was a magnificent display of trained and disciplined valour, and its assault only failed of success because dead men can advance no further." Major-General Sir Beauvoir de Lisle (commander, British 29th Division) regarding the Newfoundland Regiment at Beaumont-Hamel.