Calgary Code Camp -- Taking CI to the Next Level

Yesterday I was at Calgary Code Camp to present on Taking Continuous Integration to the Next Level.  James, Bill and group ran a remarkably smooth and organized event.  The venue was fantastic and, from a speakers perspective, the equipment and rooms were easy to work with and in.  I'm not sure what the final attendance figures were, but the rooms had a vibrant and energetic feel from the attendees.

I was slotted up in the last presentation block of the day.  I had a good group of attendees who, although quiet, did ask some good leading questions.  It was the first time I'd presented on this topic and the response I heard after was that the topic was a good one and the content was useful.  Here's a brief synopsis of the content.

  1. ReSharper makes working with your nAnt build scripts much easier than the traditional notepad approach to editing.
  2. CCNetConfig can help you setup your CruiseControl.NET server without the hassle of notepad XML editing or knowledge of the configuration file structure.
  3. CruiseControl.NET's Iteration labeler is very useful when working in agile sprints or iterations.
  4. nCoverExplorer and nCoverRunner make integration into CruiseControl.NET seamless and effortless.
  5. The nAntContrib project provides a bunch of extra nAnt tasks, including CodeStats, for your building pleasure.
  6. CruiseControl.NET's dashboard.config file allows for customization and extension of the CruiseControl.NET build website.
  7. Utilizing the functions provided with nAnt, along with some thoughtful solution structuring, can make it very easy to limit the execution of tests suites when changes haven't been made.
  8. nAnt provides great functionality in the area of creating AssemblyInfo.cs files.
  9. nAnt allows for the use of inline C# code functions which can be useful for specialized build steps.
  10. CruiseControl.NET can be used for more than just building your executables and assemblies.  Consider it for automating your deployment tasks as well.

Here's the link to the deliverables from my presentation (4mb).  Note that you will need to install version 1.2.1 of CruiseControl.NET to use the ccnet.config and dashboard.config files.  I've also included the xsl file that will do a simple summary transformation of the codestats output.

Calgary Code Camp Tomorrow

I'll be at Calgary's Code Camp tomorrow (April 28th, 2007) out at the U of C.  After all us Edmontonians ran away with last years swag, James and Co. decided to have us speak so that we won't get any swag this year.

My presentation (3:45 in the room with the dancing girls) is on Taking Continuous Integration to the Next Level.  I'm going to cover some great tools for setting up CCNet, adding functionality to nAnt and some things you can do in your build scripts that will reduce your build time and increase the capabilities of your build.

Come on out.  It's free and you get to make fun of Justice.

Published at

Some Meetings are Anti-Productive

During the last week I've had to sit in on some significantly disturbing meetings.  Let me set the record straight, I usually attend a number of disturbing meetings each week, but these did stand out because of the complete lack of planning that went into them.  Both of these meetings were to discuss the file structure and file locations on one specific network drive.  Prior to the meeting I had no idea what the purpose of it was, but alas, I decided I should probably go because it's in these types of innocuous meetings that you usually end up getting a mess to clean up.

I attended the first meeting to find eight people in the room with one laptop, one projector and one mouse.  Very quickly it was apparent to me that the meeting was one where we would all sit around and yell out folder names and where we thought they should be located.  Meanwhile one nervous person would run the mouse and attempt to keep up with the volley of commands from the cheap seats.  My immediate thought was "Ooooo....1 1/2 hours of endless fun!"

Here's what I learned in that meeting.

  • More people doesn't increase productivity (Mythical Man Month).  8 people can not run 1 mouse any better than 1 person can.
  • Timing is everything.  Reorganizing files and folders while other people are using them usually doesn't create the results you are looking for.  MS Word's file locking feature can lead to some unkind popup error messages claiming that files can't be moved.  Don't believe the messages and try again with the same results.  I once heard that this is the definition of insanity.  I think that's appropriate for this meeting.
  • Understanding your subject is useful.  Nothing brings more confidence to a person than hearing "I don't know what that file is.  Just delete it."  Hang on....I don't know what that silly DatabaseConnection.cs file is doing in our code repository.  One second while I delete it.
  • Knowing your tools is helpful.  If you are doing an exercise where you must copy files and folders, you will most likely have occasion to rename a folder.  I assume that it's also a skill that must be in the toolkit of the person who is running the one mouse.  If it isn't you can, very easily, spend 10 minutes having people yell out directions to the mouse operator.

You may think I write this tongue-in-cheek.  I don't.  All of this did happen.  None of it is made up.  How am I sure.  Well, not only was I there, but the only thing that helped me to keep my sanity was taking notes on the idiocy that swirling around me.

My case against weak-typed languages

Before you read this post in it's entirety, you need to head over to Justice Grays blog and see his post on his Grandmother and the difference between strong-typing and weak-typing.  Instead of placing an unsanctioned guest blog post in the comments section of Justice's blog, I decided to write it up here.

I do believe that the one thing Justice didn't explicitly state in his post was that in being strongly typed I would fail immediately. D'Arcy, on the other hand, will fail at only when he tries to use his Saved By The Bell DVD as a martial aid. The difference here is that I'm failing fast (one of my favourite agile principles) while D'Arcy will fail slowly (people from Winnipeg are a little slower by the nature of the narrow provincial family tree).

Justice is right when he states that unit testing in weak type languages is more important because of this D'Arcy's tardiness. My problem with that is that you've now taken the type verification away from the compiler (which will run exactly the same every time) and placed it on unit test. True that the unit tests will run the same every time (assuming that you don't build test dependence into your test suite), but it raises the question of how good are your tests.  More to the point it raises the question of how good is the coverage in your tests.  Since a weak-typed language won't fail until the guilty line of code is executed, code coverage becomes much more important than any other metric that you look at.  Because we can generate weak-type based errors, it now becomes prudent for us to include tests in our test suite specifically for these scenarios.  So now we've modified our list of testing variations to include state based, process based and type based which also implies that that I will have to spend time on writing more tests and that I will have to maintain more tests. 

When I'm writing code I work with one large underlying principle.  Give the client what they want.  I also work to provide the client with what they want in a timely fashion.  My clients don't want unexpected failures at run time.  If I can avoid some of those failures by employing a strong-typing and compile time checking, I will have immediately eliminated a whole classification of defects that the client can report.  If I don't have to worry about weak-typing errors, I also won't have to write and maintain a whole classification of tests.  This will improve my ability to provide value to the clients in a timely fashion.

The short version of this posts is that I'm not a fan of weak-typed languages because they add overhead to the development process in the form of potentially increasing the number of reported defects and, as you attempt to limit the reported defects, an increase in the amount of time spent writing and maintaining unit tests.  For some people this may not be a primary concern in their development and that is fine.  For my clients and I defects and time (which is money in development-land) are always a primary concern.

CreateMock Live Template Update

After some playing around in RhinoMocks I realized that my Create Mock Live Template wasn't nearly as elegant as it could have been.  I've updated the import file here.  This version uses the ability to create a mock object using the generic method CreateMock<T> and thus eliminates the nasty looking type cast that the old one had.  Instructions for downloading and importing can be found here.

Calgary Code Camp

The announcements have been made.  The cake has been ordered.   And the open bar* has been stocked.  Calgary Code Camp is set for April 28th at the University of Calgary.  A few of us from up here in the Capital region are heading down to present.  I'll be talking on Taking Continuous Integration to the Next Level.  Hope to see you there.

Published at

Writing unit tests

Yesterday I was bored.  When you take this bloke out of the Igloo and it's to warm to his tongue stuck to a parking meter he tends to write manifestos.  This one stemmed from having to fix a test fixture that failed when the tests were run in random sequence.  The result was an email outlining what I think are the primary concerns each developer should have when they write their unit tests.  These were my thoughts (expanded a bit because sometimes I care to share more with you than my coworkers).

  1. Never create module level object variables in your test fixtures so that they can be reused in many tests.  Often this will cause false positives and negatives simply due to test execution sequence.  Creating new objects in every test is preferable as it allows you to know that the starting state of those objects is clean and pure.  There can be exceptions to this rule such as creating one MockRepository (RhinoMocks) that is used to create mock objects across all tests.  If you're going to break this rule you'd better be able to justify it to me without breaking any of the other rules listed here.
  2. Treat tests as a specification of what the code under test should be doing.  If you read a test without reading the code, you should be able to say, with confidence, how the code under test is expected to perform.  I'm a firm believer that refactoring tests decreases your ability to adhere to this principle.
  3. Don't refactor test code to the same extent that you refactor application code.  Test code is utilitarian by nature and also requires high levels of readability (see point #2) and maintainability.  Because of this test code should not be exceptionally, or even remotely, elegant.
  4. If you find that you're struggling to write tests that cover all expected behaviours of the code, or to get a test to pass, then the code under test is probably too complicated.  Complex tests are an indication of complex code, which in turn should be an immediate sign that the code under test needs to be refactored to adhere to Single Responsibility Principle.  When I do code reviews, complex tests fully qualify as a code smell.
  5. Never write tests that rely on other tests to be executed either before or after that test.  A unit test should be an encapsulated piece of work that is ignorant of all external functionality and sequencing with the exception of the method that it is testing and the Setup and Teardown methods.
  6. Avoid mixing process (RhinoMocks.Expect.Call(...)) and state (NUnit.Assert.AreEqual(...)) based tests in the same test method.  This relates back to readability and documenting the expectations of the code under test(see point #2).  If you write one test for process based testing, I know exactly how to expect the code under test to behave with regards to it's dependencies.  If you write another test for state based testing, I know exactly how to expect the test to work with regards to its data.  Mix the two together and I have a muddled concoction of data and dependency information presented to me and it takes more effort to separate the two and clearly understand each.

Of these 6 points, number 6 has proven to be the most controversial at work.  I will readily admit that it is more rooted in personal preference than the other 5, but I think that I'm backing up my personal preference with some decent reasoning.  If anyone has anything to add (more points, better/different explanations) I'm all ears.

Edmug's 1 Year Anniversary Party

A year has come and gone, and Edmug is flourishing.  In the past 12 months we've managed to hold 13 meetings and one code camp that have seen some of the most recognized names in .NET development visit and present in Edmonton.  In addition to the luminaries we've sown the seeds of presentation with a number of locals who've provided fantastic content.

To celebrate the past year we're throwing a party!  No, it's not going to be one of those parties where Justice continually harasses you for calling his Paladin a Wizard.  Instead it's going to be one of those parties that would do service to the author of this blog.  We're going to blend geek with beer at Maverick Brewery in downtown Edmonton (map) on Thursday, April 26th.  The beer begins flowing at 5:30.

At 6pm we're going to start the presentations.  We've lined up a great local speaker, Christians Izquierdo, who's going to talk on "How to create and use Domain Specific Languages and Software Factories".  The presentation promises to be fantastic.  The event promises to be filled with drunken revelry, geeky goodness, *huge* swag and compulsory ridiculing of Justice.

Why Gmail continues to win me over

I've been using Gmail for a few years now.  For the past year or so I've been managing my Gmail accounts in Outlook.  About a month ago Outlook quit sending messages for me (I think it's related to putting VSTO onto my system, but a fresh build is upcoming so I'm not working to hard at fixing it) and I've been using the web UI a lot more.

Little things continue to impress me.  I like how it can figure out what emails belong in a thread, even if they haven't been part of a Fwd or Reply chain.  Today I got a shipping notice in one of my Gmail accounts and it really impressed me to see what Google had put in the side bar.  One click and I could be at the tracking page for my shipment.

Of course I didn't notice that until after I'd opened a new tab, navigated to UPS and cut and paste the tracking number into their webpage.  Little things like this are what get users stoked about an application.  As a developer it's extremely difficult to figure out what, when and where to put these little nuggets.  "Dog fooding" your application will give you a better chance at winning over your users, but in the end it you really need to ask them for ideas, listen intently and then take action.

Published at

Code Coverage on Constructor Based Dependency Injection

I was working with nCoverExplorer at work this week checking to see how diligent we'd been while writing our tests.  One of our major tasks in the last month has been to refactor our service layer so that it employs constructor based dependency injection.  When I looked through the coverage on this work I noticed that the coverage was lower than I'd been hoping for.  Closer inspection showed that the culprit was the constructor chaining we were using as part of our Dependency Injection refactoring. 

Below is an example of a class that we would create.

namespace DependencyInjectionExample
{
    public class DIExample
    {
        private readonly IDependency _dependency1;
        private readonly IDependency _dependency2;

        public DIExample():this(new SomeDependency(), new AnotherDependency()){}

        public DIExample(IDependency dependency1, IDependency dependency2)
        {
            _dependency1 = dependency1;
            _dependency2 = dependency2;
        }

        public void SomeMethod(string value)
        {
            _dependency1.DoStuff(value);
            _dependency2.DoStuff(value);
        }
    }
}
And here is an example of how we would test it.
using MbUnit.Framework;
using Rhino.Mocks;

namespace DependencyInjectionExample
{
    [TestFixture]
    public class DIExampleTests
    {
        private MockRepository _mockery;

        [TestFixtureSetUp]
        public void Setup()
        {
            _mockery = new MockRepository();
        }

        [TestFixtureTearDown]
        public void TearDown()
        {
            _mockery.VerifyAll();
        }

        [Test]
        public void SomeMethod_ShouldCallAppropriateMethods()
        {
            IDependency mockDependency1 = (IDependency) _mockery.CreateMock(typeof (IDependency));
            IDependency mockDependency2 = (IDependency) _mockery.CreateMock(typeof (IDependency));

            mockDependency1.DoStuff(string.Empty);
            LastCall.IgnoreArguments().Repeat.Once();
            mockDependency2.DoStuff(string.Empty);
            LastCall.IgnoreArguments().Repeat.Once();

            _mockery.ReplayAll();

            DIExample diExample = new DIExample(mockDependency1, mockDependency2);
            diExample.SomeMethod(string.Empty);
        }
    }
}
When you run this test through nCover you get this.

ConstructorCoverage

Because my only test, which I believe to be the only one necessary, uses the parameterized override of the constructor, the default constructor does not get executed.  In this example that means that code coverage drops from 100% to 78% which is below the threshold of 90% that I strive for.  I could easily write another test that creates the object using the default constructor, but I don't see why I'd write that test.  In my mind it doesn't bring any benefit to the test suite.  I realize that code coverage metric are not metrics of quality and this is why I don't see the benefit.

My question to all of you is this:  What do you do in this situation?

.Net vNext (Orcas) and TimeZone2

One of the new features in C# 3.0 (more appropriately .NET 3.5) is the addition of the TimeZone2 object.  TimeZone2 greatly enhances your ability to work with different time zones over the older implementation, TimeZone. You can see the enhanced interface provided by TimeZone2 (on the right) over TimeZone (on the left).

TimeZone TimeZone2

The the biggest change that I noticed right away is the introduction of a list of system time zones.  You can access and iterate the list as simply as:

foreach (TimeZone2 timeZone in TimeZone2.GetSystemTimeZones())
{

      Console.WriteLine(timeZone.Id.ToString() + "(" + timeZone.BaseUtcOffset.ToString() + ")");

}

Which will output:

TimeZone2Output

Another big difference is the replacement of the CurrentTimeZone property with the Local property.  With the change in property name also comes a change in return type.  TimeZone2.Local will return you a TimeZone2 object with all the goodness that the new class provides.

The last feature that I liked was the ConvertTime method.  It allows you to provide a DateTime object for conversion and tell it what time zone to convert it to.  If you're working with a database that stores time information in Greenwich Mean Time (+/- 0 hrs) and then working a bunch of code to display it to your user in their local time zone, your job has just gotten easier.  What you can do now is this:

Console.WriteLine("Converted Time: " + TimeZone2.ConvertTime(someDateTimeFromDatabase, TimeZone2.Local));

This is a trivial example that of course wouldn't work on a web or application server, but to do that all you'd have to do is provide the client's time zone as a TimeZone2 object and use it as the second parameter.

It's that time of the year again

For the next week you're going to be opening your feed aggregator of choice only to be inundated with the "I got an MVP!" posts.  If you're like me you'll be thinking "Yeah-yeah-yeah.  Congrats to you, now gimme some geeky goodness on your blog again."

For what it's worth I think the MVP program is good for our industry.  As a user group leader (Edmug's 1 year anniversary is coming up in April...more on that in another post), the MVP designation tells me that I can count on that individual to show up and present with some semblance of competence.  It's also easier to sell an MVP speaker to our members just because of the perceived knowledge level that they hold.

Why this post?  Well, let's just say the email I got from Microsoft on Sunday morning wasn't an April Fool's Day joke.  Now if only I could get the damn MVP site working so I could use the logo.  Ah well, I suppose I'm supposed to know something about C# not website usage.  I do look sexy in red though don't you think?