Sunday, November 25, 2007

Developer Developer Developer Day 6

I had a great time at DDD6 on Saturday. The nicest thing for me was getting to meet and talk to some of the most highly regarded people in the UK developer community like Dave Sussman, Dave Verwer, James Winters and Paul Lockwood. There were also a few familiar faces from Brighton there: Simon Harriyot (of Sussex Geek Dinners fame), Jane Dallaway from Madgex and Steve Mason from Cubeworks.

My talk 'Why do I need an Inversion of Control Container' got off to a bad start when I discovered that there was no way of attaching my Macbook's DVI plug to the projector. I should have known there would be some bad voodoo bringing a Mac into the heart of Microsoft, or thinking again, maybe I just should have brought the right plug. Duh and double duh! I was saved by Phil Winstanley who very kindly jumped in and lent me his laptop and helped me get up and running, thanks Phil! Ten minutes of transferring files and installing Testdriven.net later,everything worked and I was able to start. I must admit the panic meant that I was more than a bit flustered, I missed a whole load of good points I wanted to make and my tendency to talk too fast was probably attenuated somewhat.

Luckily it was an excellent crowd with some great questions. By the end of the talk I was really enjoying myself. Thanks to everyone who came up to talk afterwards, I really appreciated your feedback, especially the lady who pointed out that I hadn't said where you can get the Castle Windsor download from. Duh again! In order to rectify that oversight, you need to install the entire Castle Project which you can get here:

http://www.castleproject.org/castle/download.html

Here are the slides and demo code. The code requires the castle project and NUnit to work.

http://static.mikehadlow.com/Mike.IocDemo.zip

There should also be a video at some point; watch this space.

Tuesday, November 20, 2007

Hammett on Microsoft's MVC Framework

Here's an interesting post by Hammett, the leader of the Castle Project and writer of the Monorail MVC framework. He was invited up to Redmond to play with the MS MVC Framework. His attitude is very mature; he says that he won't bother with Monorail 2.0 if everything he wants from an MVC framework is supplied by MS. There's obviously a great deal of mutual respect going on. I wonder how long before Hammett's working for The Beast?

Installing Visual Studio 2008

Visual Studio 2008 is now available to MSDN subscribers. I downloaded it over night and have just started the install on Vista Ultimate. It's taking a long time and is currently stuck on installing Framework 3.5 with the progress bar at 0% for more than ten minutes.

... Later, it's done. But that was the longest install I've experienced for a long long time! And I have to restart Vista.

Thursday, November 15, 2007

Ian Cooper on MVC

Ian Cooper (of the London .NET User Group fame) has a very thoughtful series of posts on Model View Controller architecture:

Part 1

Part 2

Part 3

He's also doing a session on Monorail at DDD6. Which should be most interesting.

It's funny, but Microsoft's announcement of their MVC framework has raised more interest in Monorail that it could ever have on it's own. Previously it was a well regarded, but slightly obscure web development framework, but now it's got the 'copied by Microsoft' endorsement, everyone's talking about it.

Sunday, November 11, 2007

An important new .NET language: LOLCODE

I've just come across this fantastic new langauge: LOLCODE. I'm probably a little too old to ever be an expert at it because it's designed specifically for people who have grown up with texting; people who can succinctly express their ideas in abbreviated form. In true Code Rant 'love of fibonacci' fashion, here's a fib sample from John Lam's blog:

HAI
CAN HAS STDIO?
I HAS A FISH ITZ "Yummy"
VISIBLE FISH
VISIBLE "HAI WORLD!"

I HAS A FIB
I HAS A A ITZ 1
I HAS A B ITZ 0

GIMMEH FIB

IM IN YR LOOP
 VISIBLE B

 IZ FIB SMALR 1?
 YARLY
   GTFO
 NOWAI
   VISIBLE "NOWAI"
 KTHX

 I HAS A TEMP ITZ A UP B
 LOL A R B
 LOL B R TEMP

 NERFZ FIB!!
KTHX
KTHXBYE

No, it's not a joke (well not entirely), this is a real .NET language written with the DLR.

The MVC framework and new C# 3.0 features

You can't get hold of the MVC framework itself yet, but Scott Hanselman has posted the demo code used to demonstrate it at DevConnections and the PNPSummit. Browsing the routing demo code initially left me quite confused until I realized that it was using a couple of new C# 3.0 features: object initializers and anonymous types to initialize the routing engine.

using System;
using System.Web.Mvc;

namespace HelloWorld {
    public class Global : System.Web.HttpApplication {
        protected void Application_Start(object sender, EventArgs e) {

            // Custom "pretty" route
            RouteTable.Routes.Add(new Route {
                Url = "products/[category]",
                Defaults = new {
                    controller = "sample",
                    action = "ShowProducts",
                    category = "beverages"
                },
                RouteHandler = typeof(MvcRouteHandler)
            });

            // Default route
            RouteTable.Routes.Add(new Route {
                Url = "[controller]/[action]/[id]",
                Defaults = new { action = "Index", id = (string)null },
                RouteHandler = typeof(MvcRouteHandler)
            });
        }
    }
}

It initially looks like named arguments, but in fact it's creating a new anonymous type with the named properties. But how does the Route object parse its Defaults property? Does it have to use reflection to find the properties of the Defaults type, or am I missing something?

Friday, November 09, 2007

T-SQL Fibonacci and the power of 'With'

It's amazing how things can pass you by. I only found out about the recursive power of the T-SQL 'with' statement today. With it you can easily write a Fibonacci sequence generator:

with fib(a, b) as
(
 select 0, 1
 union all
 select b, a+b from fib where b < 100
)
select a from fib

Here's the output:

a
-----------
0
1
1
2
3
5
8
13
21
34
55
89

It really comes into its own when you've recursive structures such as a tree in your schema. Take this extremely typical example: a hierarchy of locations. Each record has a primary key 'id' and a foreign key 'parentId' that references another record in the same table.

locationTable

Here are some records:

locationRecords

Say I wanted to output all the locations with their level in the hierarchy. Easy:

with locationLevel(id, [name], [level]) as
(
 select id, [name], 0 from location where parentId is null
 union all
 select location.id, location.[name], locationLevel.[level]+1
 from location
 join locationLevel on location.parentId = locationLevel.id
)
select * from locationLevel

id          name                 level
----------- -------------------- -----------
0           World                0
1           UK                   1
2           France               1
5           Paris                2
6           Rouen                2
3           London               2
4           Brighton             2

Or when I search for a particular location, I want to find all its ancestors:

with locations(id, parentId, [name], targetName) as
(
 select id, parentId, [name], [name] from location
 union all
 select location.id, location.parentId, location.[name], locations.[targetName]
 from location
 join locations on location.id = locations.parentId
)
select id, [name] from locations where targetName = 'Rouen'

id          name
----------- --------------------
6           Rouen
2           France
0           World

Sunday, November 04, 2007

My new MacBook

My chum Richard just got back from a jaunt over the pond to New York. Before he left he very kindly asked if there was any shopping he could do for me. Not wanting to pass up the chance to get some cool tech at US prices, I asked him to pop into the Apple store and swag me a MacBook. For my US readers, you have to understand that as the dollar sinks into oblivion there's always an opportunity for US companies to make a few quid (bucks to you) by not slavishly following the exchange rate. Anyway Richard was true to his word and here it is...

macbook

It's the bottom of the range Apple laptop, but it's still considerably more powerful than my two year old dell desktop. Richard picked it up for almost exactly £600 which is £100 less than I'd pay for one in the UK. Not an incredible saving, but not at all bad either.

I love Apple hardware, they can actually do design; unlike every other PC manufacturer. Of course, as a windows software developer, I could never justify buying one no matter how much I like OSX, but now that they run on Intel processors and you can install windows it's a no brainer. I think a lot of other people share the same view because Apple's sales have gone through the roof. I would even consider buying a mac pro next time I need a desktop, although I was quite inspired to build my own after reading about Jeff Altwood building Scott Hanselman's from scratch.

I really like OSX, its eye-candy is so much better than Vista's, that there's really no competition. But I must have Vista, so after a quick play with Leopard, I fired up boot camp and got to work. Like most Apple stuff, boot camp is very nicely thought out and easy to use. You simply decide how much space you want to give your windows partition and click 'go' (or whatever); it partitions your hard drive, asks you to insert your Vista DVD and reboots into the Vista installer. The install went without any problems apart from once, when it came up from a reboot and stuck on a blank screen with the fan going full blast. I thought that was the end of it, but after doing a hard reboot, it came back to life into the last section of the Vista install. After Vista comes up, you insert the OSX DVD and it automatically installs all the drivers for the MacBook's hardware. The driver support is pretty impressive. Everything works: The keyboard's hardware control keys, the trackpad with it's double-touch scroll feature, the iSight camera and even the little remote control. I especially like the double touch scrolling on the touch pad. You just drag two fingers across and it acts just like It's a scroll wheel. Very intuitive. You right click by holding two fingers on the pad while clicking, which isn't quite as nice as having a button and requires too much hand contortion for my liking. All together it's a  pretty compelling package, especially if, like me, you've got an MSDN subscription and don't have to pay for a copy of Vista.

Now of course young Richard didn't go all the way to New York and not get a shiny new gadget for himself. Oh no. He returned to blighty the proud owner of an iPhone. Since they're not on sale in the UK until the end of next week, it was the first time I've seen one in the flesh. I was very impressed. The UI is superb; easily the best I've seen on a mobile device. The web browser is really cool. It's actually useable, unlike every other mobile device I've seen. My son has a PSP, which has wifi and a browser, but it's so hard to use that apart from one brief experiment I've never done any surfing with it. The iPhone's browser is, if anything, maybe more intuitive to use than a desktop browser. Being able to scroll around the page with your fingers is really nice and the screen is just big enough that you can a see a decent amount of text at once. I want one.

Friday, November 02, 2007

Inversion of Control, Unit Tests and Mocks

This is the second part of an on-going series about Inversion of Control. The first was:

What is Inversion of Control?

And I plan to do a few more digging deeper into the wonderful world of IoC. Hmm, nice.

OK, so now I want to talk about how IoC can help you to test your classes / components. As an aside, I'm really not sure whether to say 'class' or 'component' these days. We are essentially talking about individual classes, but by leveraging IoC you can make your classes more component like. I'll try and expand on this train of thought in one of my future posts. But, getting back to the point, I want to show how IoC is almost essential if you are going to do meaningful unit testing and how you can use Mock objects to completely isolate the class under test.

Do you remember this code from the last post, a little reporter class that gets some reports from a ReportBuilder and then sends them with a ReportSender:

public class Reporter
{
    public void Send()
    {
        ReportBuilder reportBuilder = new ReportBuilder();
        List reports = reportBuilder.GetReports();

        ReportSender reportSender = new ReportSender();

        // send by email
        reportSender.Send(reports, ReportSendType.Email);

        // send by SMS
        reportSender.Send(reports, ReportSendType.Sms);
    }
}

Now what if we want to write a unit test for Reporter? How about this:

[Test]
public void OReporterTest()
{
    Reporter reporter = new Reporter();
    reporter.Send();
}

What happens when we run this test? In my little demo application it outputs some stuff to the console. In a real world scenario the ReportBuilder class might get it's list of reports from a relational database via a data access layer. The data access layer might need configuration. The ReportSender might rely on an email library and an SMS library. They might also need configuration. The logging might rely on a logging library, also configurable, it might write to the machine's application log. There might be helper functions from other places in our application.

If we run this test, unless we do some very sophisticated work hooking up email and SMS clients and poking into in the application log we are probably going to rely on manually checking our email in-box, our mobile phone's text messages and visually inspecting the application log to see if our little Reporter class has done its job. All that work just for a class method five lines long.

We might do this once or twice while we're writing Reporter, but we're unlikely to bother every time we change some other part of the application. But say we change something in the data access layer, who's to say that won't break Reporter, or how about when some other class wants to use ReportSender, but in a slightly different way that requires a change that breaks Reporter? We wont find out that Reporter is broken until some time later in System testing, and that's if we're lucky.

And there's more craziness. When we test Reporter, we're not just testing reporter, we're testing the data access layer, the relational database, the email library, the SMS library, the configuration, the logging... the list goes on. What if it doesn't work? What do we do? That's right, we fire up the debugger and spend the next half an hour stepping line by line through our application scratching our head wondering why the hell it doesn't work.

All for five lines of code.

Now remember our other reporter that used Inversion of Control. It took a ReportBuilder, a ReportSender and a ReportSendLogger (yuck, did I really make up that name) in its contructor:

[Test]
public void ReporterTestWithLogging()
{
    IReportBuilder reportBuilder = new ReportBuilder();
    ILogger logger = new Logger();

    // send by email
    IReportSender emailReportSender = new ReportSendLogger(new EmailReportSender(), logger);
    Reporter reporter = new Reporter(reportBuilder, emailReportSender);
    reporter.Send();

    // send by SMS
    IReportSender smsReportSender = new ReportSendLogger(new SmsReportSender(), logger);
    reporter = new Reporter(reportBuilder, smsReportSender);
    reporter.Send();
}

Now in a real world scenario, the way this test is currently written we have exactly the same problems as our simpler non-IoC-reporter I was complaining about above. If we run the test we're testing a large chunk of our application and there's no way for the test itself to know if it's passed or not; we'd have to manually check it.

This is where mock objects come to the rescue. I've written about them before here and here. They are basically replacement instances of our dependencies that can tell us what has happened to them. When I first started to do unit testing I used to write my own, but in the last couple of years I've become a convert to using a mock object library, my favorite now is Rhino Mocks. Here's the same test as above but using mock objects:

[Test]
public void ReporterTestWithMocks()
{
    // create mock objects
    IReportBuilder reportBuilder = mocks.CreateMock<IReportBuilder>();
    IReportSender reportSender = mocks.CreateMock<IReportSender>();

    // create the reports
    Report report1 = new Report("Report 1");
    Report report2 = new Report("Report 2");
    List<Report> reports = new List<Report>();
    reports.Add(report1);
    reports.Add(report2);

    // record expectations
    Expect.Call(reportBuilder.GetReports()).Return(reports);
    reportSender.Send(report1);
    reportSender.Send(report2);

    // run the test
    mocks.ReplayAll();

    Reporter reporter = new Reporter(reportBuilder, reportSender);
    reporter.Send();
    
    mocks.VerifyAll();
}

First we create mock versions of IReportBuilder and IReportSender. 'mocks' is an instance of the Rhino mock's MockRepository. Then we create some reports for our IReportBuilder to return. The next three lines of code are the really interesting ones. We record what we expect to happen to our reportBuilder and reportSender inside our Reporter instance. When we use our mock objects before the call to mocks.ReplayAll(), the mock object framework simply records what happened. Last of all we create our Reporter and call the Send() method. When we call VerifyAll(), Everything that happened to the mock objects after ReplayAll() is compared to what happened before. If the before and after series of events are different an exception is thrown which causes the test to fail.

The really cool thing about this test is that it only tests Reporter. Nothing else. If the test fails the reason will be obvious. The test is entirely automated. We can run it with hundreds; thousands; of other tests quickly enough that there is no overhead to execute all our unit tests frequently. certainly quickly enough to make sure we never check in any code that causes any of the tests to fail.

If you adopt Test Driven Development, you'll notice all kinds of unexpected side effects. One that I didn't expect was that I've almost stopped using the debugger.

Another really interesting side effect is that we don't actually need concrete versions of IReportBuilder or IReportSender to run this test. We can write Reporter before we write our ReportBuilder or ReportWriter. This is counter to the usual bottom-up way of writing applications where you have to have your lower level code in place before you can write the high level stuff. It lets you adopt a top down style; thinking about high level concerns first and then filling in the details.

In my next post on the amazing world of IoC, I'm going to talk about IoC patterns other than the constructor dependency-injection I've shown so far.