CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Karl Seguin

developer @ Fuel Industries ottawa, ontario

June 2006 - Posts

  • TDD Lesson 2 - Continuous Integration

    I hate to digress from the raw TDD discussion so early on, but if you're serious about TDD, you have to consider whether continuous integration (CI) is right for you or not. Even if you aren't doing TDD or unit testing, many teams will find CI useful. For example, if your team is split up across the world (or even the country) the last thing you want is for Team B to have to deal with Team A's broken build. Of course, CI isn't only useful for geographically challenged teams. If I had to guess, I'd say you'll easily make up the initial time investment.

    For n00bs to CI, the point is to ensure your code is always buildable and that all unit tests always pass. Basically, a CI solution hooks into your source control server, detects that a change was made, and rebuilds/retests your code automatically. The most common solution, CruiseControl.NET comes with a system tray utility that warns you when something goes wrong. In other words, if anyone breaks a build or makes a test fail, you're little icon turns red and you'll get a bubble warning. From there, you can opt to see detail information about what exactly failed and fix it!.

    CruiseControl.NET simply monitors your source control repository, it's NAnt that actually builds and runs your code. The last time I was personally responsible for setting up NAnt was a couple years ago and it was a real pain. Now I see that they have a Solution task that makes everyone's life easier. The last thing I want to do is write a tutorial for CruiseControl.NET and NAnt, but I do want to share my configuration files, in case they help someone else


    <project name="OLMD" default="build" basedir=".">
     <property name="releaseMode" value="debug" overwrite="false" />
     <property name="baseDir" value="c:\builds\" overwrite="false" />
     <property name="deployDir" value="${baseDir}olmd\" overwrite="false" />   
     <property name="reportDir" value="${baseDir}reports\olmd\" overwrite="false" />      
     <property name="projectDir" value="${deployDir}\olmd\" overwrite="false" />         
     
     <target name="build">
      <vaultgetfile url="http://s1"
                    username="username"
                    password="pass"
                    repository="Fuel"
                    path="$/1/Fuel/"
                    destination="${deployDir}/Fuel"/>

       <vaultgetfile url="http://s1"
                     username="username"
                     password="pass"
                     repository="Fuel"
                     path="$/1/Olmd/"
                     destination="${deployDir}"/>
                        
      <solution configuration="${releaseMode}" solutionfile="${projectDir}\olmd.sln" />
         
      <call target="test" />
      <call target="clean" />           
     </target>

     <target name="clean" description="remove all generated files">
      <delete dir="${deployDir}" />
     </target>
       
     <target name="test" failonerror="true">
      <nunit2>
       <formatter type="Xml" usefile="true" extension=".xml" outputdir="${reportDir}" />
       <test assemblyname="${projectDir}\olmd\bin\${releaseMode}\Fuel.Projects.Olmd.dll" />
      </nunit2>
     </target>
    </project>


    Basically, the Build target (which is default), checks out 2 projects from Vault, and uses the wonderful Solution task to build everything. The Test target then uses the nunit2 task to run my unit tests with all reports sent to a global report directory. Finally, everything's cleaned up.


    The CruiseControl.NET configuration is even simpler (mostly because I copied and pasted most of it from the CC.NET website):

    <cruisecontrol>
     <project name="OLMD">
     <webURL>http://s2/ccnet/</webURL>
     <triggers>
      <intervalTrigger seconds="30" />
     </triggers>
     <modificationDelaySeconds>10</modificationDelaySeconds>
     <sourcecontrol type="vault" autoGetSource="false" applyLabel="false">
      <executable>c:\program files\sourcegear\vault client\vault.exe</executable>
      <username>user</username>
      <password>pass</password>
      <host>s1</host>
      <repository>fuel</
    repository>
      <folder>$/1/</
    folder>
      <ssl>false</
    ssl>
      <useWorkingDirectory>false</
    <useWorkingDirectory>
     </sourcecontrol>
     <tasks>
      <nant>
       <
    executable>C:\builds\Nant\bin\nant.exe</executable>
       <baseDirectory>C:\builds\Nant-Config\</
    baseDirectory>
       <
    <buildArgs/>
       <buildFile>olmd.build.xml</
    buildFile>
       <targetList>
        <target>build</target>
       </targetList>
       <buildTimeoutSeconds>300</
    buildTimeoutSeconds>
      </nant>
     </tasks>
     <publishers>
      <merge>
       <files>
        <file>C:\builds\reports\olmd\*.xml</file>
       </files>
       </
    merge>
       <xmllogger />
      <
    /publishers>
     </project>
    </cruisecontrol>


    Here we tell CC.NET to use Vault and how to use it (you can get this extension from SourceGear's website for free) and tell it what to do when it detects a change - namely to run our NAnt build script above. The last thing to do is point it to the reports NAnt created.

    I seem to remember this being a much bigger pain to set up, but this time it didn't take more than 1/2 an hour to set up (I had a bug in CC.NET which I eventually fixed by disabling all versions except 2.0). With CI in place, we're ready to continue TDD'ing.

    Posted Jun 26 2006, 10:26 AM by karl with 8 comment(s)
    Filed under:
  • TDD Lesson 1 - Don't worry about starting small

    The first thing I want to cover in my "learning TDD" track is to not worry about writing seemingly meaningless or uninteresting code. First of all you never know what shape code will take in the future – the simplest of tests might help prevent a subtle bug. Secondly, it won't be long before you start to write more interesting code, so hang tight!

    That said, for the first couple minutes I didn't even know HOW to start. I knew that I wanted to start with a core class in my domain (an Indicator). Indicators do all sorts of interesting stuff, but since I'm writing tests first, I don't even have an Indicator class!  To solve that little problem, I wrote the only test that made sense:

    [TestFixture]
    public class IndicatorTest
    {
     [Test]
     public void CanCreateIndicatorInstance()
     {
      Indicator indicator = new Indicator();
      Assert.IsNotNull(indicator);
     }
    }


    Of course the code won't build. So I create a new class "Indicator" and make sure the default constructor is there. I know that in theory you're supposed to make the test fail - but making my constructor throw a fake exception for the same of making it fail doesn't seem worthwhile. It's entirely possible that I'll opt to go with only factories for my Indicator class, but for now, this is the quickest way to get started.

    Next, I know that every Indicator will have an Name, so I write my next test:

    [Test]
    public void CanSetIndicatorName()
    {
     Indicator indicator = new Indicator();
     Assert.IsNull(indicator.Name);
     indicator.Name = "Test Indicator";
     Assert.AreEqual("Test Indicator", indicator.Name);
    }


    So I go into my Indicator class and create a straightforward private _name field with a public Name property. Two points here. I could have easily made the test fail, but figured the broken build was good enough. Also, I agree that a public field would be the simplest solution here, but that violates our coding standards.

    The Indicator class has a number of similar properties, so I write similar tests for all the ones I know about. Admittedly it isn't particularly fun and it doesn't feel too productive, but it's only a couple minutes of my time. There's an urge inside of me pushing me to take a bigger leap, but I keep it in check.

    That's it :) I know it isn't much, but I had such a hard time accepting this way of starting, I figured others might also. I promise things will quickly get more interesting (though I think next post I might take a little break and go over nANT and CruiseControl.NET).

    On a side note, as much as people talk about the importance of unit tests when it comes to refactoring, I honestly see them as even more useful when working in a team. The CanSetIndicatorName test tells the other developers on the project that someone expects the Name property to be null and NOT string.Empty when a new instance is created. If anyone changes my field declaration to _name = string.Empty, the test will fail and hopefully they'll think twice about their change, else risk breaking code somewhere they weren't away of.

    Technorati Tags: , ,


    Posted Jun 23 2006, 09:49 AM by karl with 13 comment(s)
    Filed under:
  • Becoming more Agile : I'm learning TDD

    Unlike many of my CodeBetter colleagues, I'm not the most Agile developer in the shed. Specifically, I've never done TDD for a real system. I'm more of a unit-test-after kinda guy, which often (not always) translates to unit-test-never. When surrounded by advocates, it can be intimidating for an ignoramus to speak up.  Luckily, on the same day David reviewed "Applying Domain-Driven Design and Patterns : With Examples in C# and .NET" by Jimmy Nilsson, I started working on a project ideally suited for TDD. (On a side note, I plan on giving the book a detailed review once I'm done.)

    Rather than quietly learning TDD, I thought it better to share my experience in the hopes of helping others. TDD might be popular here at CodeBetter, but that's the exception to the rule in the .NET community.

    If you are totally new to domain driven design (ie, maybe you use DataSets a lot..ya ya, they aren't mutually exclusive, leave me alone) , have no exposure to unit testing and don't know anything about the open-source trio (nUnit, nAnt, CruiseControl.NET) you have a huge job ahead of you. Personally, I'd recommend you familiarize yourself with domain driven design on a number of small sample projects – writing code that manually maps between your domain and data model. Hopefully there's someone in your team that can help you out.

    The very first piece of advice I'd give to anyone wanting to learn TDD is to wait for the right project. I called my project "ideally suited for TDD" for three main reasons:
    1. It isn't particularly difficult
    2. I have a strong understanding of the domain (business)
    3. The client is cool
    I can't imagine learning TDD on a difficult project with a hard to understand domain and a rigid client. Specifically, I think having a strong understand of the domain has really helped out – it's a huge load of my learning curve.

    So far, I've found very little quality material on the web that'll help you out (maybe I'm looking at the wrong place?!). Most tutorials simply spit out text book material. They'll have the image that shows the typical TDD flow (write the test .. make it build .. make it fail .. make it pass .. refactor). Come on, give me some concrete examples! Jimmy's book actually provides you with those real examples, but it'd still be nice to be able to draw from a greater collection of samples. I'm blown away that there isn't a simple TDD example of testing a User class somewhere on the web (I understand that it isn't' that straightforward because you'll quickly hit the persistence layer).

    Another great piece of advice is to keep things simple. I've always been a huge proponent of YAGNI (you aren't going to need it) and I find that while trying to make a test pass, the simplest solution is almost always best – even if I know it won't be the final solution. I've always programmed like this, but the granularity of unit tests and the instant feedback from TDD makes it very natural to achieve.

    Over the next couple weeks, I'll be posting some material squarely aimed at TDD newbies like myself. Hopefully the experts will correct any mistakes I make – I'm certainly not afraid of making mistakes when learning something new. I've created a new category (look to your left) called TDD for this material.

    Oh, and in case you haven't figured it out. I strongly recommend you buy "Applying Domain-Driven Design and Patterns : With Examples in C# and .NET" by Jimmy Nilsson. In no way am I affiliated in any way with this book. Again, I do hope on giving a detailed review in the near-ish future.

    Technorati Tags: , ,
    Posted Jun 21 2006, 12:51 PM by karl with 11 comment(s)
    Filed under:
  • I would quit before working with Rational

    Rational, which was bought by IBM awhile ago, sells a range of products aimed  at large-scale enterprise development. Requirement management, bug tracking, source control, modeling, etc. There are two problems with Rational – it’s insanely expensive and insanely bad software. We had 2 full time Rational "administrator, bought 70 hours of Rational consultation every 3 months and put every developer and manager through 2-5 day courses.  Oh ya, we spent a small fortune on licenses (like 6K a pop or something crazy).  You can’t save money by not going on the course either, because "checking out" a file doesn’t actually "check it out" and "checking in a file" doesn’t actual "check it in". You want to "rebase" and "deliver" – which of course you can’t do from VS.NET.

    Partial integration is a real pain in the ass, but it’s better than XDE’s (Rational’s modeling tool) broken integration. You see, Rational works via floating licenses. You don’t use a license unless you are actually doing something. In theory, this means you don’t have to buy every developer a license (what are the chances that 100% of your developers are checking out a file at the same time?) Forget the fact that you hold on to a license for 30 minutes, and at 8:00AM or 4:30PM a lot of developers ARE actually trying to do source control operations. So where does XDE fit into this? Well, since XDE is a VS.NET add-on, having VS.NET open – even if you aren’t using XDE – means you’re eating a license. Thanks Mr. Rational, here’s another $20K.
    I’m sure there are really big teams out there that need products like Rational. For the rest of us, there are only two good reasons to go the [ir]Rational route:
    1. It’s expensive so it must be good
    2. It’s needed for RUP
    Hopefully you know those are both lies. For your sake, your manager better know it too!

    When the pricing for VSTS came out, it blew my mind that people were complaining. Obviously the people complaining most have no idea what people are willing to pay for bad software that does this!  VSTS is a steal – end of story.

    What else is wrong with Rational?
    • Every time anyone opened the source control client, we’d get an index out of range error. We were told that we had too many baselines in our project. Sorry for doing continuous integration.
    • The UI sits on top of a rational shell with Unix-like commands. Not too bad, but anything remotely advanced and you’ll need to do it in the shell
    • You’ll spend tends of thousands of dollars and still have to use nANT, nUnit and CruiseControl.NET. (I have no problems with those tools, but for that kind of money, I’m expecting a fully integrated end-to-end solution).
    • All the applications are English only (someone please tell me that I’m wrong on this one, I still can’t believe it)
    • Poor to No integration with the IDE
    • Horrible UIs – Create a new Bug and you’ll see about 4 ClearQuest internal items in the new menu – no way to hide them.
    • This might have changed but on the heels of .NET 2.0 Rational still hadn’t committed to continuing their support for VS.NET
    • You will need a ClearCase and ClearQuest administrator

  • Poor .NET search results on Google

    I wouldn't mention anything, but I'm sure this problem is relatively new, and growing. It used to be I could search for .NET things via google and get a bunch of great hits in the first couple results. Lately though, I'm finding I'm having to scroll down or reword my search query.

    For example, if I search for ArrayList the first page contains 2 .NET related links - in the 7th and 8th spots! Java stuff is everywhere else. I realize other frameworks have "ArrayList", but I'm sure just a couple months ago I was getting much better results.

    Search for Math.Round and you'll find no .NET entries, java.sun.com is #1 again though. Same story for String Class.

    This isn't a google issue either, MSN search returns very similar results. Java documentation seems to be getting indexed much better. What's up with that? Like I said, my solution is generally to append c# or msdn to my query.

    While I'm on the topic, who the heck gives the System.String documentation on msdn2 a rating of 1? How can the average rating from 36 people be 3? Let people rate the documentation and provide comments (because I've found bugs before, submitted them and gotten prompt feedback) but don't display an "average" rating -my  guess is that some Slashdot kiddies are having fun with you.


  • Global.asax? Use HttpModules Instead!

    In a previous post, I talked about HttpHandlers - an underused but incredibly useful feature of ASP.NET. Today I want to talk about HttpModules, which are probably more common than HttpHandlers, but could still stand to be advertised a bit more.

    HttpModules are incredibly easy to explain, so this will hopefully be a short-ish post. Simply put, HttpModules are portable versions of the global.asax. So, in your HttpModule you'll see things like BeginRequest, OnError, AuthenticateRequest, etc. Actually, since HttpModules implement IHttpModule, you actually only get Init (and Dispose if you have any cleanup to do). The Init method passes in the HttpApplication which lets you hook into all of those events. For example, I have an ErrorModule that I use on most projects:

    using System;
    using System.Web;
    using log4net;

    namespace Fuel.Web
    {
     public class ErrorModule : IHttpModule
     {
      #region IHttpModule Members
      public void Init(HttpApplication application)
      {
       application.Error += new EventHandler(application_Error);  
      }      
      public void Dispose() { }
      #endregion

      public void application_Error(object sender, EventArgs e)
      {
        //handle error
      }
     }
    }

    Now, the code in my error handler is pretty simple:

    HttpContext ctx = HttpContext.Current;
    //get the inner most exception
    Exception exception;
    for (exception = ctx.Server.GetLastError(); exception.InnerException != null; exception = exception.InnerException) { }
    if (exception is HttpException && ((HttpException)exception).GetHttpCode() == 404)
    {
     logger.Warn("A 404 occurred", exception);
    }
    else
    {
     logger.Error("ErrorModule caught an unhandled exception", exception);
    }


    I'm just using a log4net logger to log the exception, if it's a 404 I'm just logging it as a warning.

    You can do this just as easily with a global.asax, but those things aren't reusable across projects. That of course means that you'll end up duplicating your code and making it hard to manage. With my ErrorModule class, I just put it in a DLL, drop it in my bin folder and add a couple lines to my web.config under <system.web>:

    <httpModules>
     <add  name="ErrorModule" type="Fuel.Web.ErrorModule, Fuel.Web" />
    </httpModules>


    And voila, I have a global error in place.

    In almost all cases, you should go with HttpModules over global.asax because they are simply more reusable. As another example, my localization stuff uses an HttpModule as the basis for adding a multilingual framework to any application. Simply drop the DLL in the bin and add the relevant line in your web.config and you're on your way. Here's the important code from that module:

    public void Init(HttpApplication context)
    {
     context.BeginRequest += new EventHandler(context_BeginRequest);
    }
    public void Dispose() {}
    private void context_BeginRequest(object sender, EventArgs e)
    {
     HttpRequest request = ((HttpApplication) sender).Request;
     HttpContext context = ((HttpApplication)sender).Context;
     string applicationPath = request.ApplicationPath;
     if(applicationPath == "/")
     {
        applicationPath = string.Empty;
     }
     string requestPath = request.Url.AbsolutePath.Substring(applicationPath.Length);
     //just a function that parses the path for a culture and sets the CurrentCulture and CurrentUICulture
     LoadCulture(ref requestPath);
     context.RewritePath(applicationPath + requestPath);
    }


    If you are developing a shrink-wrap product, you don't have a choice but to use HttpModules, because the last thing you want is to ship a global.asax which the user must use, overwriting the code in his own global.asax.

    The only time you want to use Global.asax is when using OutputCaching with the VaryByCustom property. As far as I know, the GetVaryByCustomString function _must_ be placed in the global.asax file.

    Anyways, switching from Global.asax to HttpModules is pretty straightforward. So I encourage you to look at where it makes sense (ie, where you see the potential for reuse across applications) and make it so.


  • ASP.NET Job @ Blizzard

    I wasn't going to blog about it, but there's a Lead Tools Programmer job available at Blizzard Entertainment. You can see the full job posting here. If they are smart, they'll hire an MVP or someone with a strong community presence.

    I could be wrong, but I'm pretty sure past jobs at blizzard that weren't directly involved in gaming were of the Java variety. Of course Blizzard isn't the most successful game company in the world because it repeats past mistakes Wink [;)]

    Anyways, if anyone lands this dream job and reads this blog, I'm expecting 2 Legendary staves - one for me and one for the girlfriend!

    Am I the only one that would kill for the chance to build ASP.NET sites that interact with the WoW database? Web-based messaging and auction house tools so you can play some part of WoW while @ work :)
  • 1. WinFX/XAML 2. Office 2007

    I just have to talk about two somewhat off topic subjects, so I'll keep it quick: WinFx/XAML and office 2007.

    I downloaded the newest WinFX beta for Windows XP, along with the VS.NET 2005 tools and the CTP of Interactive designer. Woah...my first thoughts were (a) this is how it should be and (b) things are gonna change. Specifically I was thinking that those ugly gray VB6 apps are going to be a thing of the past -for the most part. You gotta wonder why it took so long, I mean it seems so logical. I can't say that I'm a fan of declarative programming and the learning curve seems really steep. I think many people/organizations are going to have to face the reality that programmers aren't designers anymore. As for the technology themselves, WinFX seems very stable, but Interactive Designer is obviously a very premature product. It's stable, but slow and not particularly user friendly. I think it might actually be dogfooding WinFX - what a horrible mistake.

    (The flash guys here are skeptical but seem willing to give it a go once it's stable and WPF/e comes out)

    As for Office 2007. Install it. It's rock solid on 3 machines that I've put it on. As a writer, Word 2007 is absolutely freakin amazing. It looks great, it works great, the new features are useful. Everything about it, including the new font, is perfect. I hope they create an update to Word 2003 so that it can open docx files.

    Outlook though is a different story. It crashes about 5-6 times a day (which isn't the end of the world) and it totally misses out on the entire Office remake. It looks just like Outlook 2003 with a right-sidebar (which you can probably turn on in 2003 anyways...). It's like the ugly grey duckling..totally out of place. Open Excel, PowerPoint, Access and you have the new office 2007 look which is great. Infopath, Outlook, Publisher and you feel like you've wasted your money - plus the user experience is horrible because the menu systems are completely different (try changing the theme in outlook (10 minutes to find it) vs word (1 minute to find it)

    Using office 2007, I can't help but wonder what the heck is going on at Microsoft. Vista is delayed, the betas are really betas and it's overhyped with a bunch of features removed. You hardly hear anything about Office 2007, it comes out in beta, totally solid and loaded with a bunch of features you never knew you wanted but are sure you are going to use.

    All these betas/ctp's are publically available via Microsoft.com. Just do a google search. As always, know what you are getting into when installing pre-release software. Just because office runs great on my machine, doesn’t' mean it will on yours!

More Posts