Monday, September 08, 2008

Managed Extensibility Framework: Why?

Sometimes... no often... I'm quite dumb. I've been skimming through posts about the MEF thinking that people were talking about the Entity Framework (Microsoft Entity Framework :). I only realised that it was something new today. So what is it. Well it looks like an IoC container, but the spin is that it's different from other IoC containers because it's primarily aimed at providing an extensibility model; a common way for applications and frameworks to load types from dropped-in assemblies. This is from the CodePlex MEF site:

"MEF presents a simple solution for the runtime extensibility problem. Until now, any application that wanted to support a plugin model needed to create its own infrastructure from scratch. Those plug-ins would often be application-specific and could not be reused across multiple implementations.

MEF provides a standard way for the host application to expose itself and consume external extensions. Extensions, by their nature, can be reused amongst different applications. However, an extension could still be implemented in a way that is application-specific. Extensions themselves can depend on one another and MEF will make sure they are wired together in the correct order (another thing you won't have to worry about).

MEF offers a set of discovery approaches for your application to locate and load available extensions.

MEF allows tagging extensions with additional metadata which facilitates rich querying and filtering"

The thing is, although they're selling it as a plug-in framework, it does look very much like any other IoC container,  so it's odd that they're making the plug-in pitch when they could be providing a generic IoC framework. There doesn't seem to be anything about it which precludes using it in the general IoC role, except that they say it's not optimised for that.

So it begs the question: are the MEF team suggesting that we support two IoC frameworks in our applications? One for plug-in extensibility, the other to support internal component based architecture?

It seems to me that it would not be very hard to provide an IoC container that can successfully cover both these requirements. I haven't tried it, but I imagine it would be quite simple to provide a facility for Windsor to load assemblies from a file location, for example.

This one is going to run and run...

Tuesday, September 02, 2008

What's up with Linq to NHibernate?

With my current clients I'm building an MVC Framework application using NHibernate. I love NHibernate. Like all the best frameworks it just works for most common scenarios. I'm a new user, but I've been able to get up to speed with it very quickly. The power and flexibility of the mapping options make it easy to use with the legacy database that we're lumbered with. But the best thing about it though, is that it's built from the ground up for Domain Driven Development. This means it's possible to build a finely grained domain model unencumbered by data access concerns.

Seriously, if you're building .NET enterprise level business software and you haven't considered using NHibernate (or a competing ORM) you missing out on a huge productivity win.

Any ORM targeting .NET has to support Linq. Here the NHibernate story's not so good at the moment. The coding phenomena that is Ayende kicked off the first Linq to NHibernate implementation a while back. It was originally part of his Rhino Tools project and layered the Linq implementation on top of the NHibernate criteria API. This has now been moved to the NHibernate contrib project. The source is here:

http://sourceforge.net/projects/nhcontrib/

I've been using this in my current project, it works but only with the most straightforward queries. Anything tricky tends to fail and I've tended to go through a process of trial and error to find the right patterns. The problem seems to be mostly around the criteria API. It doesn't support a lot of the features that Linq requires, especially nested queries.

Recently a new NHibernate.Linq project has been started in the NHibernate trunk that takes a different approach. The authors are building SQL directly from the expression tree which obviously gives a lot more flexibility. The intention is to also to convert HQL to an expression tree thus having a single uniform query translation.

This is very exciting for NHibernate but there's going to be a hiatus while the new implementation evolves.

Thanks to Tuna Toksöz for the info.

Monday, September 01, 2008

Vote For Me! (again)

Voting has opened for this year's Developer Developer Developer Day at Microsoft's UK Headquarters near Reading. You can vote for the sessions you want to see here:

http://www.developerday.co.uk/ddd/votesessions.asp

I've put forward a couple of talks:

Why do I need an Inversion of Control Container   (Style: Presentation - Level: 100)
Inversion of Control (IoC) containers such as Unity Windsor and Structure Map are a hot topic in the Microsoft Development world. What are they and why is there such a buzz about them? How will they help me build better applications? Join me on a trip to an parallel universe of application architecture where I show how IoC containers at last make component oriented software development a reality.

This will be an updated version of the talk I gave at last year's DDD. I'll try and compress the 'why' and have a little more of the 'what' this time.

Using an Inversion of Control Container in a real world application   (Style: Presentation - Level: 200)
Going beyond an initial introduction to IoC containers, this talk shows their use in an open source eCommerce application, Suteki Shop. I will show how the IoC container helps us write component oriented software and can significantly simplify both our architecture and code. This will include a look at some nice techniques such as generic repositories, using IoC containers with the MVC Framework and how they can help us host services.

A more in-depth look at how an IoC container helps with a real world application. I'm really looking forward to showing off the generic repository pattern and WCF integration in this one. The problem is going to be cramming everything in.

Wednesday, August 20, 2008

Taking the HttpContext out of the MVC Framework Controller

I really like the MVC Framework. I'm currently working on my third commercial project using it and I just love the flexibility it gives me, especially the opportunity to refactor the framework itself.

Here's an example: one of the things I dislike is the way the default Controller class is overly coupled to the HttpContext. HttpContext in itself is a problematic hangover from ASP.NET and to have it bound into the Controller to such an extent is a design mistake IMHO.

OK, so what do I mean? Take this action code from a controller:

public ActionResult Search()
{
    const int pageSize = 20;

    var criteria = new ArticleSearchCriteria();
    validatingBinder.UpdateFrom(criteria, Request.Form);

    var articles = articleRepository
        .GetAll()
        .ThatMatch(criteria)
        .ToPagedList(PageNumber, pageSize);

    return View("Search", View.Data
        .WithArticleSearchCriteria(criteria)
        .WithArticles(articles));
}

You see the reference to Request.Form there? The HttpRequest (and HttpResponse and HttpContext) are all exposed as properties of the base Controller class. In order to test that code I have to mock the HttpContext which is a real PITA.

Here's an alternative that I've started using. An IHttpContextService interface:

public interface IHttpContextService
{
    HttpContextBase Context { get; }
    HttpRequestBase Request { get; }
    HttpResponseBase Response { get; }
    NameValueCollection FormOrQuerystring { get; }
}

I can now just use Dependency injection in my controller to get a reference to an implementation of IHttpContextService. Note I don't care here how it is implemented:

public class ArticleController : ControllerBase
{
    private readonly IRepository<Article> articleRepository;
    private readonly IHttpContextService httpContextService;
    private readonly IValidatingBinder validatingBinder;

    public ArticleController(
        IRepository<Article> articleRepository, 
        IHttpContextService httpContextService,
        IValidatingBinder validatingBinder)
    {
        this.articleRepository = articleRepository;
        this.httpContextService = httpContextService;
        this.validatingBinder = validatingBinder;
    }

    public ActionResult Search()
    {
        const int pageSize = 20;

        var criteria = new ArticleSearchCriteria();
        validatingBinder.UpdateFrom(criteria, httpContextService.FormOrQuerystring);

        var articles = articleRepository
            .GetAll()
            .ThatMatch(criteria)
            .ToPagedList(PageNumber, pageSize);

        return View("Search", GroupLibView.Data
            .WithArticleSearchCriteria(criteria)
            .WithArticles(articles));
    }
}

And I can set up my IoC container to give me any implementation of IHttpContextService I want. Now because the IHttpContextService is provided by the IoC container, any dependencies that its implementation may require can also be provided by the IoC container which opens up all kinds of interesting opportunities.

Here's my current HttpContextService:

using System.Collections.Specialized;
using System.Web;

namespace Suteki.Common.Services
{
    public class HttpContextService : IHttpContextService
    {
        public HttpContextBase Context
        {
            get
            {
                return new HttpContextWrapper2(HttpContext.Current);
            }
        }

        public HttpRequestBase Request
        {
            get
            {
                return Context.Request;
            }
        }

        public HttpResponseBase Response
        {
            get
            {
                return Context.Response;
            }
        }

        public NameValueCollection FormOrQuerystring
        {
            get
            {
                if(Request.RequestType == "POST")
                {
                    return Request.Form;
                }
                return Request.QueryString;
            }
        }
    }
}

More on MSTest

I recently had a long and considered comment from Woonboo for my post "MSTest is sapping my will to live". Woonboo is a happy user of MSTest. I started writing a reply in the comments, but it was getting so involved I thought it would be nice to promote it to a new post.

Here's Woonboo's comment:

I know I'm late to the game, but mileage is everything.

I used to use NUnit, but after using MSTest for the past 2.5 years, I wouldn't go back, even with the bugs in VS2008 (which are minor and only hit if you are doing something specific with AppDomain).

Your config file thing is simple - you don't have to use attribute...in the 'settings' (right-click properties) add files to deploy.

It creates a separate test project because too many Morts out there will just put it in the same project otherwise and all your tests will be deployed with the code. I've worked with a number of these folks.

Having the built in ability to test private and internal methods/properties/fields is the biggest reason I love it. No extra code required. No need to loosen the scope (make things public) on what you're testing.

When a test fails, looking at the test results that gives me a hyper-link to every part of the stack trace where the test failed (or threw an exception) as saved me hundreds if not thousands of hours by now not having to navigate to the file, hit CNTL+G and enter the line number; especially if I have to walk up the stack to see if there was a path taken that shouldn't of been causing the problem.

Having the ability to have tests run automatically when I do a build or check-in (easier than I was ever able to with NUnit - but that's a SCC).

Code coverage gets tied to the tests you write.

Pulling up archives into the GUI of who ran what tests when on what machines. Great from the 'team lead' perspective.

You said in another post that technologies change but methodologies don't - don't let NUnit suck you into the 'one tool' mentality (although I could say the same about myself with MSTest). Love your posts generally - but I think you need to give MSTest another chance and ask someone who's been successful with it for help. It was hard for me to switch from NUnit too - but it was like when I switched from VB to C# - I never looked back once I got past the frustration point.

Woonboo's points get to the nub of the problem for me: I don't think MSTest was designed for TDD but for some other high-ceremony style of integration testing. I would submit that he is probably not working in that style. Let me take his points one by one to explain what I mean.

"you don't have to use attribute...in the 'settings' (right-click properties) add files to deploy". Yes, but I shouldn't have to do even this. Why can't it just test what's in the target directory? Building a separate run directory for every test and forcing the user to deliberately choose files to deploy is just another symptom of the high-ceremony MSTest approach.

"It creates a separate test project because too many Morts out there will just put it in the same project otherwise and all your tests will be deployed with the code." I agree that it's best to have a separate test project. But any testing framework should be unintrusive. I shouldn't have to have a separate project type. The only reason it's needed by MSTest is because MSTest requires so much configuration to be useful. And you shouldn't rely on project types to force you to correctly organise your source, otherwise we'd have some crazy Microsoft scheme to have the "domain-project", the "data-access" project, the "service-project". Don't suggest that too near to someone from the TFS team!

Now I have to have a rant here about "The Morts won't understand it" argument. I hear this over and over and over again. It usually goes along the lines of "I understand it fine, but the people I work with, or the 'maintenance' people won't". It's the lamest and most often deployed excuse for bad decisions. If the Morts can't understand something, whoever they are, get rid of them. What's the point in employing people who don't know how to do their job? But usually it's not the real reason, the real reason is lack of leadership, and lack of trust. Most advances in development practices actually make things simpler but it requires that you, if you are the team lead, sit down and work with the people you are supposed to be leading.

"Having the built in ability to test private and internal methods/properties/fields is the biggest reason I love it." One of the core reasons for doing TDD is way it drives your design. If you have to access private members in your tests I would submit that your design is not correctly decoupled. I *want* my testing framework to force me to behave like any other client when I'm writing tests.

Now there might be a situation where you have to write tests for some monolithic legacy code base, but MSTest won't help your there, you need to go and talk to Roy Osherove :)

"When a test fails, looking at the test results that gives me a hyper-link to every part of the stack trace where the test failed." You get exactly the same thing with Testdriven.NET. I have "run-tests" mapped to F8 (I've never found a use for bookmarks). "Run-tests" is context specific so if the cursor is currently inside a test method, only that test gets run. So I just hit F8 to run the test(s), the results appear on the console and I can click on any part of the stack trace to go directly to that line of code. I actually dislike fancy test runners. I don't want to have to click here and there to get to stack traces, I'd much rather everything was just thrown onto the console.

Of course running tests on your CI server is essential. I've always found it simple to do that both with Cruise Control and TFS. I don't think MSTest really adds much here and it doesn't make much sense unless you're using TFS.

"Pulling up archives into the GUI of who ran what tests when on what machines. Great from the 'team lead' perspective." OK, I don't get this. Surely what you should be looking at is code coverage. I run tests every few mintues when I'm coding, you probably wouldn't want to look at or store all those test runs. I think this goes back to my first point. A tool that's designed for high ceremony infrequent testing like MSTest would see storing a test run archive as a useful thing, anyone who's done TDD would see it as a huge waste of resources.

I gave MSTest a chance. I've also recently tried to use MBUnit. neither worked as well as TestDriven.NET + NUnit do for me. I must say that MBUnit came very close, and I wouldn't have too much problem with using if I was in a team that has already settled with it. MSTest was just a nightmare from start to finish. As I said to our project manager, if it was an open source tool, it would never have got any traction and would now be sitting unloved in sourceforge. Maybe it suits some people with a very non-agile, non-TDD methodology, but for anyone doing TDD I would stay well clear.

Woonboo. Thanks very much for provoking me to write this. I love a good debate and would really like to hear your reply. Thanks again!

Sunday, August 17, 2008

Firefox wins here (just)

I use the excellent Google Analytics for tracking stats on my blog. One of the things it tells me is the browser that you, dear reader, are using:

browser_stats

browser_pie

I guess I shouldn't be too surprised that a technical readership should marginally prefer Firefox. But it's still very nice to see.

What else can I tell you about yourself? Well you're probably American.

countries

country_stats

I had an interesting discussion in the office last week. I'm British, but I suggested that since the majority of my readership is from the USA I should adopt US spelling. Even mentioning such a thing was like finding a raised toilet seat in a nunnery, so rather than being lynched I'll stick to 'through' rather than 'thru'. It's a marginally interesting factlet that English speaking kids take almost twice as long to read and write than most other European countries because of the awfulness of our spelling.

One last thing, and this really does surprise me: The vast majority of traffic to my blog is driven by Google searches which is the result of random people typing in random search terms and then finding their way here. The curious thing is that the numbers are so consistent. Every week looks the same with between 200 and 250 visits during week days and 50 to 70 at the weekends. I would have expected more variation, but I guess it's a good demonstration of the predictability of randomness that it's like this.

searchtraffic

Wednesday, August 13, 2008

What's an Auto Mocking Container?

An auto mocking container (AMC) sounds pretty scary, but it's a really neat tool if you're writing a lot of unit tests and find yourself forever constructing mock objects. In the same way that an IoC container knits together dependencies at runtime, an AMC can create all your mock objects automatically for your unit tests.

Say you are testing this Reporter class

public class Reporter
{
  private readonly IReportBuilder reportBuilder;
  private readonly IReportSender reportSender;

  public Reporter(IReportBuilder reportBuilder, IReportSender reportSender)
  {
      this.reportBuilder = reportBuilder;
      this.reportSender = reportSender;
  }

  public void SendReports()
  {
      var reports = reportBuilder.GetReports();

      foreach (var report in reports)
      {
          //reportSender.SendReport(report);
      }
  }
}

Using Rhino.Mocks you might do something like this.

[Test]
public void SendReports_ShouldCreateReportsAndSendThem()
{
  // create the mock services that the Reporter requires
  var reportBuilder = MockRepository.GenerateStub<IReportBuilder>();
  var reportSender = MockRepository.GenerateStub<IReportSender>();

  // create the reporter, injecting the mock services
  var reporter = new Reporter(reportBuilder, reportSender);

  // create some reports
  var report1 = new Report();
  var report2 = new Report();
  var reports = new[] {report1, report2};

  // when the reportBuilder mock's GetReports method is called, return the reports
  // we created above
  reportBuilder.Expect(rb => rb.GetReports()).Return(reports);

  // excercise the method under test
  reporter.SendReports();

  // verify that the reporter sent the expected reports
  reportSender.AssertWasCalled(rs => rs.SendReport(report1));
  reportSender.AssertWasCalled(rs => rs.SendReport(report2));
}

After the tenth time you've had to write this kind of code you get quite bored of typing the mock object creation. It's irritating when you're thinking about using a new dependency in an existing class, and you have to add it to both the class under test and the setup for the test.

Here's an example using the AutoMockingContainer from Rhino Tools.

[Test]
public void SendReports_ShouldCreateReportsAndSendThem_WithAMC()
{
  // create a new auto mocking container
  var mocks = new MockRepository();
  var container = new Rhino.Testing.AutoMocking.AutoMockingContainer(mocks);
  container.Initialize();

  // just ask for the reporter
  // the container will automatically create the correct mocks
  var reporter = container.Create<Reporter>();

  // create some reports
  var report1 = new Report();
  var report2 = new Report();
  var reports = new[] { report1, report2 };

  // when the reportBuilder mock's GetReports method is called, return the reports
  // we created above
  container.Get<IReportBuilder>().Expect(rb => rb.GetReports()).Return(reports);

  // expect that the reporter sent the expected reports
  container.Get<IReportSender>().Expect(rs => rs.SendReport(report1));
  container.Get<IReportSender>().Expect(rs => rs.SendReport(report2));

  // excercise the method under test
  reporter.SendReports();

  // assert that expectation were met
  mocks.VerifyAll();
}

As you can see, after we set up the AMC we simply ask it for an instance of the class we wish to test. We don't have to worry about supplying the dependencies because the AMC works out what mocks need to be created and does it for us.

When we setup our expectations we can ask the AMC for the mock objects it's created.

You can get the latest version of the source code for the Rhino Tools AMC by pointing tortoise here:

https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk

Or you can download the code and grab the assemblies I've built from the trunk here

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

Monday, August 11, 2008

Microsoft.Sdc.Tasks

I just discovered this collection of MSBuild tasks. There are tasks for all kinds of things you might want to do during your build including...

  • Editing XML files using XPath
  • Setting up web sites including creating virtual directories
  • Editing registry settings
  • Setting version numbers
  • Lots of file and folder manipulation

... and lots more. I'm using its XmlFile task for changing my NHibernate-Windsor-integration IsWeb setting to false in the windsor.config file that's copied to my tests project:

<Target Name="AfterBuild">
<Copy
   SourceFiles="$(SolutionLocation)MyProject\Configuration\Windsor.config"
   DestinationFiles="$(TargetPath).Windsor.config"
   />
<Copy
   SourceFiles="$(SolutionLocation)MyProject\Web.config"
   DestinationFiles="$(TargetPath).config"
   />
<XmlFile.SetAttribute
           Path="$(TargetPath).Windsor.config"
           XPath="/configuration/facilities/facility[@id='nhibernate']"
           Name="isWeb"
           Value="false"
           IgnoreNoMatchFailure="false"
           Force="true"
   />
</Target>

Friday, August 08, 2008

The Queryable Domain Property Problem

LINQ has revolutionised the way we do data access. Being able to fluently describe queries in C# means that you never have to write a single line of SQL again. Of course LINQ isn't the only game in town. NHibernate has a rich API for describing queries as do most mature ORM tools. But to be a player in the .NET ORM game you simply have to provide a LINQ IQueryable API. It's been really nice to see the NHibernate-to-LINQ project take off and apparently LLBLGen Pro has an excellent LINQ implementation too.

Now that we can write our queries in C# it should mean that we can have completely DRY business logic. No more duplicate rules, one set in SQL, the other in the domain classes. But there's a problem: LINQ doesn't understand IL. If you write a query that includes a property or method, LINQ-to-SQL can't turn the logic encapsulated by it into a SQL statement.

To illustrate the problem take this simple schema for an order:

queriable_scema

Let's use the LINQ-to-SQL designer to create some classes:

queriable_classes

Now lets create a 'Total' property for the order that calculates the total by summing the order lines' quantities times their product's price.

public decimal Total
{
get
{
    return OrderLines.Sum(line => line.Quantity * line.Product.Price);
}
}

Here's a test to demonstrate that it works

[Test]
public void Total_ShouldCalculateCorrectTotal()
{
const decimal expectedTotal = 23.21m + 14.30m * 2 + 7.20m * 3;

var widget = new Product { Price = 23.21m };
var gadget = new Product { Price = 14.30m };
var wotsit = new Product { Price = 7.20m };

var order = new Order
{
    OrderLines =
    {
        new OrderLine { Quantity = 1, Product = widget},
        new OrderLine { Quantity = 2, Product = gadget},
        new OrderLine { Quantity = 3, Product = wotsit}
    }
};

Assert.That(order.Total, Is.EqualTo(expectedTotal));
}

Now, what happens when we use the Total property in a LINQ query like this:

[Test]
public void Total_ShouldCalculateCorrectTotalOfItemsInDb()
{
var total = dataContext.Orders.Select(order => order.Total).First();
Assert.That(total, Is.EqualTo(expectedTotal));
}

The test passes, but when we look at the SQL that was generated by LINQ-to-SQL we get this:

SELECT TOP (1) [t0].[Id]
FROM [dbo].[Order] AS [t0]

SELECT [t0].[Id], [t0].[OrderId], [t0].[Quantity], [t0].[ProductId]
FROM [dbo].[OrderLine] AS [t0]
WHERE [t0].[OrderId] = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]

SELECT [t0].[Id], [t0].[Price]
FROM [dbo].[Product] AS [t0]
WHERE [t0].[Id] = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]

SELECT [t0].[Id], [t0].[Price]
FROM [dbo].[Product] AS [t0]
WHERE [t0].[Id] = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [2]

SELECT [t0].[Id], [t0].[Price]
FROM [dbo].[Product] AS [t0]
WHERE [t0].[Id] = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [3]

LINQ-to-SQL doesn't know anything about the Total property, so it does as much as it can. It loads the Order. When the Total property executes, OrderLines is evaluated which causes the order lines to be loaded with a single select statement. Next each Product property of each OrderLine is evaluated in turn causing each Product to be selected individually. So we've had five SQL statements executed and the entire Order object graph loaded into memory just to find out the order total. Yes of course we could add data load options to eagerly load the entire object graph with one query, but we would still end up with the entire object graph in memory. If all we wanted was the order total this is very inefficient.

Now, if we construct a query where we explicitly ask for the sum of order line quantities times product prices, like this:

[Test]
public void CalculateTotalWithQuery()
{
var total = dataContext.OrderLines
    .Where(line => line.Order.Id == 1)
    .Sum(line => line.Quantity * line.Product.Price);

Assert.That(total, Is.EqualTo(expectedTotal));
}

We get this SQL

SELECT SUM([t3].[value]) AS [value]
FROM (
SELECT (CONVERT(Decimal(29,4),[t0].[Quantity])) * [t2].[Price] AS [value], [t1].[Id]
FROM [dbo].[OrderLine] AS [t0]
INNER JOIN [dbo].[Order] AS [t1] ON [t1].[Id] = [t0].[OrderId]
INNER JOIN [dbo].[Product] AS [t2] ON [t2].[Id] = [t0].[ProductId]
) AS [t3]
WHERE [t3].[Id] = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]

One SQL statement has been created that returns a scalar value for the total. Much better. But now we've got duplicate business logic. We have definition of the order total calculation in the Total property of Order and another in the our query.

So what's the solution?

What we need is a way of creating our business logic in a single place that we can use in both our domain properties and in our queries. This brings me to two guys who have done some excellent work in trying to solve this problem: Fredrik Kalseth and Luke Marshall. I'm going to show you Luke's solution which is detailed in this series of blog posts.

It's based on the specification pattern. If you've not come across this before, Ian Cooper has a great description here. The idea with specifications is that you factor out your domain business logic into small composable classes. You can then test small bits of business logic in isolation and then compose them to create more complex rules; because we all know that rules rely on rules :)

The neat trick is to implement the specification as a lambda expression that can be executed against in-memory object graphs or inserted into an expression tree to be compiled into SQL.

Here's our Total property as a specification, or as Luke calls it, QueryProperty.

static readonly TotalProperty total = new TotalProperty();

[QueryProperty(typeof(TotalProperty))]
public decimal Total
{
get
{
    return total.Value(this);
}
}

class TotalProperty : QueryProperty<Order, decimal>
{
public TotalProperty()
    : base(order => order.OrderLines.Sum(line => line.Quantity * line.Product.Price))
{
}
}

We factored out the Total calculation into a specification called TotalProperty which passes the rule into the constructor of the QueryProperty base class. We also have a static instance of the TotalProperty specification. This is simply for performance reasons and acts a specification cache. Then in the Total property getter we ask the specification to calculate its value for the current instance.

Note that the Total property is decorated with a QueryPropertyAttribute. This is so that the custom query provider can recognise that this property also supplies a lambda expression via its specification, which is the type specified in the attribute constructor. This is the main weakness of this approach because there's an obvious error waiting to happen. The type passed in the QueryPropertyAttribute has to match the type of the specification. It's also very invasive since we have various bits of the framework (QueryProperty, QueryPropertyAttribute) surfacing in our domain code.

These days simply everyone has a generic repository and Luke is no different. His repository chains a custom query provider before the LINQ-to-SQL query provider that knows how to insert the specification expressions into the expression tree. We can use the repository like this:

[Test]
public void TotalQueryUsingRepository()
{
var repository = new RepositoryDatabase<Order>(dataContext);

var total = repository.AsQueryable().Select(order => order.Total).First();
Assert.That(total, Is.EqualTo(expectedTotal));
}

Note how the LINQ expression is exactly the same as one we ran above which caused five select statements to be executed and the entire Order object graph to be loaded into memory. When we run this new test we get this SQL:

SELECT TOP (1) [t4].[value]
FROM [dbo].[Order] AS [t0]
OUTER APPLY (
SELECT SUM([t3].[value]) AS [value]
FROM (
    SELECT (CONVERT(Decimal(29,4),[t1].[Quantity])) * [t2].[Price] AS [value], [t1].[OrderId]
    FROM [dbo].[OrderLine] AS [t1]
    INNER JOIN [dbo].[Product] AS [t2] ON [t2].[Id] = [t1].[ProductId]
    ) AS [t3]
WHERE [t3].[OrderId] = [t0].[Id]
) AS [t4]

A single select statement that returns a scalar value for the total. It's very nice, and with the caveats above it's by far the nicest solution to this problem that I've seen yet.

Monday, August 04, 2008

On Google App Engine

I was just reading Ayende's post 'Thinking About Cloud Computing'. He talks about two very different approaches; Amazon's EC2/GoGrid where you have a VM that sits on Amazon's or GoGrid's servers and Google App Engine where Google provide an application hosting environment. Ayende's take is that the Google approach is the one with legs and I'm inclined to agree with him.

I've been aware of EC2 for a while now because I'm a keen user of S3, but I'd not come across Google App Engine before. I really like the premise; you simply upload your application to the cloud and it just scales as required. At the moment it only supports Python, but this is something that will surely spread to other environments. It can only be a matter of time before someone supplies a Mono based .NET environment. Once that happens Mono will move from being an interesting .NET sideshow to being seriously mainstream.

Up to now, If you're thinking of building the next YouTube or Twitter you've got two choices, you can concentrate on getting a compelling new application out there and hope that you'll be able to deal with scaling it up if it gets popular. Possibly facing a similar to fate to Twitter, which has been having serious scaling issues. Or alternatively, you spend the money up front on infrastructure. Probably wasting money on something that may never fly.

With Cloud computing you don't have this dilemma. You can concentrate on building a fantastic application knowing that you don't have to worry about the infrastructure.

What will Microsoft's response to this be? Their OS monopoly must surely be threatened by a world where anyone can get limitless scalability on a pay-as-you-go basis. Why would anyone every buy a server operating system again? Will the beast soon start selling its own cloud services?