Wednesday, August 18, 2010

Bending Linq Syntax to your will

I just read an old blog post by Wes Dyer showing how Linq Syntax uses Monads. I’ve been really struggling trying to understand Monads and learning Haskell over the last few months, and I’m really not there yet, but Wes’ post really lit a lightbulb. I’d naively thought Linq was simply all about IEnumerable<T> or IQueryable<T>, and for 99% of the examples and code out there, it is. But actually it’s far more generic than that.

Here’s a really silly example bastardised from Wes’ post. I’m going to wrap two integers in a context, or container, and then do some operation on them using Linq syntax so that I don’t have to explicitly dip into the container.

Let’s define our container first:

public class Container<T>
{
    public T Item { get; private set; }
    public string Message { get; private set; }

    public Container(T item, string message)
    {
        Item = item;
        Message = message;
    }
}

It just wraps an instance of some arbitrary type along with a message.

Next we need some extension methods, namely two varieties of SelectMany (which is effectively ‘bind’ from Haskell’s Monad), I’ve also added a ToContainer extension method, but it’s only to make things look nice and isn’t necessary for the Linq syntax to work:

public static class ContainerExtensions
{
    public static Container<T> ToContainer<T>(this T item, string message)
    {
        return new Container<T>(item, message);
    }

    public static Container<U> SelectMany<T, U>(this Container<T> container, Func<T, Container<U>> selector)
    {
        return selector(container.Item);
    }

    public static Container<V> SelectMany<T, U, V>(
        this Container<T> container, 
        Func<T, Container<U>> selector, 
        Func<T, U, V> operation)
    {
        var container2 = container.SelectMany(selector);
        return container.SelectMany(x => 
            selector(x).SelectMany(y => 
                operation(x, y).ToContainer(container.Message + " " + container2.Message)));
    }
}

Now we can use Linq Syntax to wrap two items (in this case integers) in containers, but still do operations on them without having to explicitly extract them from their containers. At the same time the containers themselves are combined as defined in the second SelectMany above:

public void LinqSyntaxWorksWithContainer()
{
    var result = from a in 3.ToContainer("Hello")
                 from b in 4.ToContainer("World")
                 select a + b;

    Console.Out.WriteLine("result.Item = {0}", result.Item);
    Console.Out.WriteLine("result.Message = {0}", result.Message);
}

Outputs:

result = 7
result.Message = Hello World

Is that not just amazing? Think of all the times you need pass around something wrapped in some context and then keep digging it out to do some operation on it, this technique could really clean up that code.

I’d very much recommend reading Wes’ blog post in full, and have a look at Monads, they are mind bending, but have the potential to radically simplify many programming challenges.

For an in depth example, check out this post by LukeH where he uses Linq Syntax to build a monadic parser. Chris Patterson has an excellent working example of such a parser in his Magnum library.

Friday, August 06, 2010

NHibernate Linq Eager Fetching

The new NHibernate Linq provider provides eager fetching out of the box. Here’s how you do it:

var customers = session.Query<Customer>().Fetch(c => c.Orders).ToList();

Note, Query<T> is an extension method in the NHibernate.Linq namespace.

The statement above will cause the following SQL to be executed:

select customer0_.CustomerId   as CustomerId0_0_,
       orders1_.OrderId        as OrderId3_1_,
       customer0_.CompanyName  as CompanyN2_0_0_,
       customer0_.ContactName  as ContactN3_0_0_,
       customer0_.ContactTitle as ContactT4_0_0_,
       customer0_.Address      as Address0_0_,
       customer0_.City         as City0_0_,
       customer0_.Region       as Region0_0_,
       customer0_.PostalCode   as PostalCode0_0_,
       customer0_.Country      as Country0_0_,
       customer0_.Phone        as Phone0_0_,
       customer0_.Fax          as Fax0_0_,
       orders1_.CustomerId     as CustomerId3_1_,
       orders1_.EmployeeId     as EmployeeId3_1_,
       orders1_.OrderDate      as OrderDate3_1_,
       orders1_.RequiredDate   as Required5_3_1_,
       orders1_.ShippedDate    as ShippedD6_3_1_,
       orders1_.ShipVia        as ShipVia3_1_,
       orders1_.Freight        as Freight3_1_,
       orders1_.ShipName       as ShipName3_1_,
       orders1_.ShipAddress    as ShipAdd10_3_1_,
       orders1_.ShipCity       as ShipCity3_1_,
       orders1_.ShipRegion     as ShipRegion3_1_,
       orders1_.ShipPostalCode as ShipPos13_3_1_,
       orders1_.ShipCountry    as ShipCou14_3_1_,
       orders1_.CustomerId     as CustomerId0__,
       orders1_.OrderId        as OrderId0__
from   Customers customer0_
       left outer join Orders orders1_
         on customer0_.CustomerId = orders1_.CustomerId

As you can see a single statement returns the customer and all the customer’s orders, just as expected.

Note that if you want to mix Fetch with other clauses, Fetch must always come last. So for example:

var customers = session.Query<Customer>().Fetch(c => c.Orders).Where(c => c.CustomerId == "ANATR").ToList();

Will throw a nasty parse exception:

Test 'NHibernate.Test.Linq.EagerLoadTests.WhereWorksWithFetch' failed: System.NotSupportedException : Specified method is not supported.

But this will work fine:

var customers = session.Query<Customer>().Where(c => c.CustomerId == "ANATR").Fetch(c => c.Orders).ToList();

Be careful not to eagerly fetch multiple collection properties at the same time. Although this statement will work fine:

var employees = session.Query<Employee>()
    .Fetch(e => e.Subordinates)
    .Fetch(e => e.Orders).ToList();

It executes a Cartesian product query against the database, so the total number of rows returned will be the total Subordinates times the total orders. Ayende discusses this behaviour here.

You can fetch grandchild collections too. Here we use ‘FetchMany’ and ‘ThenFetchMany’:

var customers = session.Query<Customer>()
    .FetchMany(c => c.Orders)
    .ThenFetchMany(o => o.OrderLines).ToList();

Which produces the following SQL:

select customer0_.CustomerId    as CustomerId0_0_,
       orders1_.OrderId         as OrderId3_1_,
       orderlines2_.OrderLineId as OrderLin1_4_2_,
       customer0_.CompanyName   as CompanyN2_0_0_,
       customer0_.ContactName   as ContactN3_0_0_,
       customer0_.ContactTitle  as ContactT4_0_0_,
       customer0_.Address       as Address0_0_,
       customer0_.City          as City0_0_,
       customer0_.Region        as Region0_0_,
       customer0_.PostalCode    as PostalCode0_0_,
       customer0_.Country       as Country0_0_,
       customer0_.Phone         as Phone0_0_,
       customer0_.Fax           as Fax0_0_,
       orders1_.CustomerId      as CustomerId3_1_,
       orders1_.EmployeeId      as EmployeeId3_1_,
       orders1_.OrderDate       as OrderDate3_1_,
       orders1_.RequiredDate    as Required5_3_1_,
       orders1_.ShippedDate     as ShippedD6_3_1_,
       orders1_.ShipVia         as ShipVia3_1_,
       orders1_.Freight         as Freight3_1_,
       orders1_.ShipName        as ShipName3_1_,
       orders1_.ShipAddress     as ShipAdd10_3_1_,
       orders1_.ShipCity        as ShipCity3_1_,
       orders1_.ShipRegion      as ShipRegion3_1_,
       orders1_.ShipPostalCode  as ShipPos13_3_1_,
       orders1_.ShipCountry     as ShipCou14_3_1_,
       orders1_.CustomerId      as CustomerId0__,
       orders1_.OrderId         as OrderId0__,
       orderlines2_.OrderId     as OrderId4_2_,
       orderlines2_.ProductId   as ProductId4_2_,
       orderlines2_.UnitPrice   as UnitPrice4_2_,
       orderlines2_.Quantity    as Quantity4_2_,
       orderlines2_.Discount    as Discount4_2_,
       orderlines2_.OrderId     as OrderId1__,
       orderlines2_.OrderLineId as OrderLin1_1__
from   Customers customer0_
       left outer join Orders orders1_
         on customer0_.CustomerId = orders1_.CustomerId
       left outer join OrderLines orderlines2_
         on orders1_.OrderId = orderlines2_.OrderId

Once again, exactly as expected.

Happy Fetching!

Tuesday, August 03, 2010

How do You Stress Test Your Web Application?

Here’s a cunning way of writing a blog post, get other people to do it for you! Luckily for me, the people who (for some reason) follow me on Twitter are a really clever lot. Yesterday I asked the question, “What do people use for stress testing their web application?” the response was so good, that it has to be recorded as a blog post.

In addition to this, you should also check out this Stack Overflow post: How to you stress test a web application, People mention JMeter, but two tools not covered here, The Grinder and Pylot get recommendations.

Here are the tools Twitter people use in no particular order:

Users

This is the tool I’ve been using as well. It works great, but users get upset when the website is stressed beyond capacity. Also I really want to see how far I can push Suteki Shop before it breaks. Up to now, it’s coped very well with the small number of users thrown at it. I want to see what happens when it gets Slashdotted – and no please, that’s not an invitation :)

WCAT

http://www.iis.net/community/default.aspx?tabid=34&i=1466&g=6

This tool is a free download from Microsoft.

“Web Capacity Analysis Tool (WCAT) is a lightweight HTTP load generation tool primarily designed to measure the performance of a web server within a controlled environment.  WCAT can simulate thousands of concurrent users making requests to a single web site or multiple web sites.  The WCAT engine uses a simple script to define the set of HTTP requests to be played back to the web server. Extensibility is provided through plug-in DLLs and a standard, simple API.”

Several people said they’d successfully used this. The major irritation with WCAT is that you have to script every request, so to be realistic you’d have to log all the requests in a typical user session and then hand-craft a script to be played back. I wonder how hard it would be to write an IIS log-file to WCAT script tool?

Loadstorm

http://loadstorm.com/

This is an cloud based service that you pay a subscription for, although they do have a free option for up to 25 concurrent users. There seem to be a few of this kind of service out there.  I guess the advantage is that you get a much more realistic scenario, an external source hammering your application, than an internal tool. Beyond that, I’m not sure why I’d use such a service.

WatiN

http://watin.sourceforge.net/

This tool isn’t really intended as a stress test tool. It’s primary use is for UI testing. It provides a nice API to launch and operate Firefox and IE so that you can write C# UI tests. However by launching multiple instances one of my correspondents has been successfully using it for stress testing. I guess my main question would be, how much hardware I would need to run enough instances of Firefox or IE to simulate high loads.

Selenium Grid

http://selenium-grid.seleniumhq.org/

Selenium is another UI test tool, similar to WatiN. It’s what I use for UI based tests. Selenium Grid allows you run to many Selenium tests in parallel. Once again, it’s primary design goal is to aid UI integration build tests, but there’s no reason you couldn’t use it run stress tests.

Selenium 2 has merged in WebDriver which can drive the headless browser HtmlUnit (see below), this might mean that sufficiently high loads can be driven from minimal hardware.

Speed Tracer

http://code.google.com/webtoolkit/speedtracer/

This is a tool from Google. It’s a Chrome extension and looks like it’s primarily designed to profile AJAX applications, especially GWT based apps. For that it looks excellent. I wonder how easy to would be to use it for stress testing a web server though. At the very least it would face the same issues as WatiN and Selenium Grid; needing a large number of Chrome instances.

HtmlUnit

http://htmlunit.sourceforge.net/

“HtmlUnit is a "GUI-Less browser for Java programs". It models HTML documents and provides an API that allows you to invoke pages, fill out forms, click links, etc... just like you do in your "normal" browser.”

This looks interesting if you don’t mind playing with Java.

“HtmlUnit is used as the underlying "browser" by different Open Source tools like Canoo WebTest, JWebUnit, WebDriver, JSFUnit, Celerity, ...”

Apache JMeter

http://jakarta.apache.org/jmeter/

JMeter, another Java tool that looks just the ticket. It’s designed specifically for load testing:

“Apache JMeter may be used to test performance both on static and dynamic resources (files, Servlets, Perl scripts, Java Objects, Data Bases and Queries, FTP Servers and more). It can be used to simulate a heavy load on a server, network or object to test its strength or to analyze overall performance under different load types. You can use it to make a graphical analysis of performance or to test your server/script/object behavior under heavy concurrent load.”

Visual Studio Ultimate - Load Test Analyser

http://msdn.microsoft.com/en-us/library/ms404677.aspx

If you’ve already paid for Visual Studio Ultimate (or been lucky enough to have been given a copy, thanks Liam!) then it’s probably worth checking this out. At first glance it looks pretty comprehensive and you get all the nice VS integration.

So thanks everyone for some great tips. If you’ve had a good (or bad) experience with load testing tools, please leave a comment. I still haven’t decided what to go with for load testing Suteki Shop. I’m leaning towards Selenium 2 + HtmlUnit, but I might give the VS LTA and JMeter a spin too. Watch this space.

Monday, August 02, 2010

You Don’t Need an Application Server

image Do you have an ‘Application Server’? For some reason it’s a very popular choice to separate web applications into a front-end UI/Controller deployment, a separate server for back-end ‘Business Services’ and have them communicate via web services. I’ve never understood why this is a good idea and I’ve come to believe that people do it because of a number of architectural misconceptions.

Before I start I want to make a clear distinction between web applications and rich client applications. Rich clients do require an application server. I’m arguing that there’s no sane reason to build one for a web application. I’m also not talking about application service ‘Application Servers’ such as WebSphere or AppFabric.

1. Don’t confuse Logical and Physical architecture.

Good software design 101 says that you should separate concerns. You shouldn’t mix up UI concerns with data access concerns, and you should separate infrastructure from business logic. This is all good advice and working out the best ways to do it is really the core task of any programmer. However, when we say ‘separate’ we mean, ‘logically separate’. This means that these concerns should be separated in the structure of your software, it doesn’t mean that they have to be in separate assemblies, and it most emphatically shouldn’t mean that they should be deployed them on separate servers. As Martin Fowler says in Patterns of Enterprise Application Architecture, ‘The first rule of distributed components is don’t distribute your components’.

Having your business logic deployed on a separate server behind web services leads to all kinds of weird design pathologies. Because your controller logic can’t access your domain logic directly you can often find either business logic leaking into your controllers and UI, and/or chatty or over-complicated web service interfaces. This often can kill performance, which is ironic since performance is often used to justify the whole application server idea.

 2. You can deploy multiple copies of the same assembly.

A common argument for application servers is that they aid reuse. By having all the business logic deployed on a single server, multiple applications will be able to reuse the same web services. For example, a fat client web forms applications will be able to share the same business logic as a web application. Messaging components will also be able to access those same web services.

The unwritten assumption is that we can only ever have one deployed copy of an assembly. However, the in-process object-oriented API of your domain entities is far better for reuse than a bunch of web services. There is nothing to stop you from having one deployment of your business logic in your web application, another in your application server that supports your rich clients and yet another in your messaging component.

It’s also often the case that when you start to have multiple applications consuming your web services, you find that their requirements are diverse enough to mean that reuse is minimal. The requirements of a request-response web application are not the same as an event driven web forms client.

3. There should only be one access point to my database.

Shared databases are a plague on business IT. Somewhere in the depths of your organisation are a tribe of grumpy trolls called DBAs. They form a protective barrier around ‘The Enterprise Database’. No one is allowed to change the schema without twenty committee meetings and two hundred pages of documentation signed in blood. No one is allowed to access the database except through stored procedures two thousand lines long, lovingly crafted over the last ten years by said DBAs. The reason for this sorry state of affairs is the horrible 90’s idea that a single relational database  can be the core repository for the entire enterprise. Of course you don’t want to repeat this mistake, so you mandate that there must only be one access point to the database; the application server.

This is very sensible, you should only have a single access point to a database. However we’re repeating the confusion between logical and physical deployment again. You should only have one logical access point, but there is no reason why you shouldn’t deploy it multiple times.

4. An application server will help me scale.

No it won’t, it will make things worse. If you have a single web server, the most scalable physical architecture is to put everything on the same box, including the database. Network calls are expensive, very expensive. Each extra network hop you require your application to make to server a request will slow it down. More resources will be taken making the network connection than you will save by moving processing to another server.

If you have multiple web servers, you gain nothing from forcing your application to talk to the database via an application server. SQL Server can easily handle multiple connections from a number of web servers, and if you have more than five web servers you are already in a new zone of scalability requirements and you should be looking at message based asynchronous architectures such as CQRS. The same applies if you have expensive processing requirements, hand them off asynchronously.

So to conclude, think carefully before you decide you need an application server for your web application. Putting all the application code on the web server is a far better approach. You can have a farm of servers sharing a single database and it will scale well. I did some consultancy for the UK property website findaproperty.com who use this approach very successfully, and Stack Overflow has a very similar architecture. Both serve around half a million page views per day, findaproperty with four web servers, Stack Overflow with two. Of course, if you are Google or Facebook, you need a different approach… and better advice than I can give.

Wednesday, July 28, 2010

Book Review: Rework by Jason Fried and David Heinemeier Hansson

image

This is the latest book from the 37 Signals duo, Jason Fried and David Heinemeier Hansson (AKA DHH inventor of Ruby on Rails). I bought it because I enjoyed ‘Getting Real’, their previous book, so much. It’s in a similar mould and is essentially an extended version of Getting Real focussing less on the product and more on the business. Jason and David’s writing style is very engaging and easy, it only took two evenings to read through the book’s 271 pages. The book is divided into 1, 2 or 3 page snippets each filling out a pithy one-liner, such as ‘Underdo your competition’, ‘Meetings are toxic’, ‘Ignore the details early on’, which makes it very nice to just dip into. In fact, it would make an excellent book to leave by the loo.

I do a lot of work in medium to large scale organisations, which can be very frustrating. A lot of the things I dislike about the way such organisations work is down to gut feeling. If we could only stop talking and listening to every single little objection, if we could only dispose of over complicated processes, if we could just start building something without having to specify everything in minute detail, if we could just create, we would be far far more efficient.  And not only that, but work would be much more enjoyable. This book is a resounding vindication and justification for such gut feelings.

The problem is that it probably wouldn’t work in most of the places I consult at. All the advice in the book is predicated on the notion that you have a small organisation of motivated and talented individuals. Just look at the authors, one of whom is the creator of one of the world’s most influential software frameworks. You don’t need a manager to get DHH to do great work. No, this is a book for alpha people who want to start their own businesses. It’s basically saying, your gut feelings are right, you don’t need managers, meetings and detailed plans, you just need to do it.

The other problem with the book is that it’s mostly about negatives, what you don’t need to do. It doesn’t really have much to say about what you do need. Ruby on Rails is such a success because it brings together best practices for developing software in an easy to use package that almost forces you to do the right thing. As software engineers, we are usually scathing of management process, but obsessive about software development practice. Throughout the book you feel that there probably is a whole raft of good practice, rules and principles being executed at 37 signals, but all they are really telling you about is the stuff they don’t do. I expect that if you naively followed their instructions without a good background in your business’s speciality, things wouldn’t go very well.

Having said all that, I really enjoyed this book. It’s a great motivator to start up your own business and has some really good things to say about designing products, earning your customer’s trust and especially how to do great marketing. Highly recommended.

Friday, July 02, 2010

Brighton ALT.NET Beers. 7pm Tuesday 6th July at The Skiff

Details are the same as last month. See you there!

Sunday, June 27, 2010

Is Microsoft the IBM of the 2010’s?

I’d like to take you back 15 years to when I was just starting out on my career in IT. Windows 95 has just been released, the internet was beginning to escape from academia and the buzz was all about client-server. The small consulting company that I worked for was very excited about getting into VB and SQL Server, but when I asked about the internet it was dismissed as a ‘fad’.

In those days Microsoft generated huge excitement and fear in the IT industry and our little company did very well from exploiting that. I remember many conversations with more senior members of the profession who told me that client-server systems could never replace their beloved AS400s, and how VB was a toy compared to Cobol. Of course they were wrong. Microsoft was rapidly taking over business computing, and before long Windows and Office became ubiquitous.

Microsoft’s business model stemmed from Bill Gates’ thought experiment: ‘what if hardware were free?’ If hardware was free, or at least a commodity, the owner of the operating system would own the IT market. Microsoft’s entire business has been based on this premise. It made Gates the world’s richest man and Microsoft the richest company. But sitting on a monopoly can make you complacent. What if someone comes along and asks the question, ‘what if software were free?’ If software were free, Microsoft’s whole foundation would be in question. The problem for Microsoft is that a lot of people have been asking that question.

Microsoft is being relentlessly squeezed from two directions.

The cloud is starting to provide a viable alternative for small and medium sized organisations. Instead of a rack of Windows 2008 servers, why not simply sign up for Google Apps for Domains? No more installing, managing, backing up of file servers and exchange, no more hunting around for users who have lost their word documents. Of course the functionality is nowhere near what Microsoft server products plus Office can provide, but lots of people don’t need all those bells and whistles. Microsoft began in the server space by replacing Oracle and Sun and IBM in smaller organisations and now Google is doing the same thing.

At the other extreme, Linux is the OS of choice if you are huge. It simply doesn’t make sense to run a server farm of Windows machines - from both a technical and a financial point of view. If all the biggest players are running Linux, it’s an easy sell for a typical medium sized company’s CTO to suggest that they should do the same. Microsoft still pretty much owns the small and medium sized server space, but it’s really now because of inertia rather than because they are a better choice.

Far more scary for Microsoft is the mobile market. This is where the action is in 2010. Two titans, Apple and Google, are locked in a struggle. Google will win, for the same reason that Microsoft won against Apple the first time around: Apple is still a hardware company. In this war Microsoft is a bystander, even though Phone 7 is undoubtedly a good product it is still a niche one. Microsoft cannot compete because their business model of selling operating system licences ties their hands before they can even get off the start line.

For now Android runs on Mobile phones, but soon there will be tablets and TV top-set boxes. Windows will be relentlessly pushed out of the consumer market. For many businesses, the temptation will be to move from Office to Google Apps and give each desk an appliance. The cost savings in both licences and support will be huge. Microsoft’s hold over both the office desktop and applications will be under threat.

The Microsoft of 2010 is looking like the IBM of the 90’s, an incumbent giant without an answer for the changing landscape around it. In the same way, I would not expect Microsoft to disappear (although that is a possibility), but they will gradually become irrelevant to the future of IT.

So what does this mean for .NET developers like you and me? Well, we could just keep doing the same old thing, but the opportunities for work will slowly wither away, much like the Cobol guys found in the 90’s. So what should we do? I personally think Objective C and iPhone development is a dead end. Google will win the mobile OS war. I’m just waiting for Nokia to give up on MeGo, accept the inevitable, and start making Android phones. HTC is looking like becoming the Dell of the 2010s.

So Android will be the new Windows. Any Linux skills will be a good thing. Java skills will help too. Server side code will run on Linux, so once again: Linux skills are good. Being able to interface with Google Apps will be an excellent skill to have, so being comfortable with the Google APIs will pay dividends. Everyone should try to build a non-trivial Android app.

What about programming languages? Here the future is less clear. I would love it if Mono took off and allowed me to take my C# and .NET skills to Linux based OSs, but I really don’t think it’s likely. The CLR is now almost ten years old and is beginning to show its age. There’s not really a compelling reason to adopt it over the JVM. I think there has to be progress in programming languages. I’m learning Haskell simply because it seems to be where all the good ideas in language development are coming from (just look at C# 3.0), but the dynamic trio of Javascript, Ruby and Python are also very exciting these days. On the browser, standards always win in the end, and the future belongs to HTML5, not to Flash, and even less to Silverlight.

One thing is pretty certain, I won’t be making any attempt to learn the plethora of Microsoft server solutions; Sharepoint, Dynamics etc. They are the final indication that MS really is becoming IBM. There’s plenty of money to be made as a reseller doing customisations for these products, but it’s no place for a geek.

So thanks Microsoft, it’s been great, but now it’s time to move on.

Friday, May 28, 2010

Brighton ALT.NET Beers. 7pm Tuesday 1st June at The Skiff

The next Brighton ALT.NET Beers will be held at the co-working venue ‘The Skiff’ at 7.00 pm on Tuesday 1st June. I’ll be hosting again.

The address is: The Skiff, 49 Cheltenham Place, Brighton, BN1 4AB


View Larger Map

The format will be the same as usual, a quick round of suggestions for topics, voting and then an evening of beer and geekery.

What better way to recover from the rigours of the bank holiday weekend?

Saturday, May 15, 2010

Skillsmatter Progressive .NET Tutorials May 12-14th 2010

This week I had the pleasure of talking at the second Progressive .NET Tutorials organised by Skillsmatter in London. I presented a four hour workshop on advanced Castle Windsor. You can watch the videos here:
Part 1
Part 2
Part 3

You can get the code from my Google Code repository here.

To be honest, I’ve been getting quite bored of being ‘windsor-man’ in the UK alt-net community and after the last time I presented my ‘introduction to IoC’ talk, I vowed I would never do it again. But doing this workshop was a lot of fun. Having four hours to get to grips with some more advanced topics was really nice. It helped that I had a very keen audience who asked some great questions and really got involved. It was also interesting to see some of the common misconceptions and problems people have with IoC containers. It seems that most confusion comes from deciding what should come out of a container and what should not. This often manifests itself in questions about factories and how you should resolve things like domain entities, or how you should do resolution within them. The simple answer is you don’t, but it’s difficult to explain what is an appropriate ‘service’ and what is not. It’s something I’m still struggling with.

I only attended the Wednesday session. I had intended to attend on Friday as well, but my teeth decided otherwise and I spent the morning in my dentist’s chair instead. So the only other session I got to see was Robert Pickering’s introduction to F# and even though I saw him do a similar talk last year, I still found it very interesting and learnt a whole load of stuff about F# that I didn’t know before.

Wendy, Skillsmatter’s boss, took all the speakers out to dinner and I had a great evening chewing things over with Dave Laribee, Scott Cowan, Toby Henderson, Ayende and Ian Cooper. But probably the most significant revelation of the day was that I finally discovered the true identity of prolific tweeter @Daneel3001 :)

Monday, May 03, 2010

10 Advanced Windsor Tricks – 13. Use SubContainers to replace dependencies on context

Here’s part thirteen of (slightly more than) 10 Advanced Windsor Tricks.

Say you have a multi-tenanted application and you want to have different components provided for different customers. One way of doing this is to create an IHandlerSelector which allows you to choose which components get provided depending on some context. It’s the technique I use for Suteki Shop’s multi-tenancy and I’ve written about it several times in the past: here and here.

An alternative approach is to use a SubContainer. SubContainers are a way to provide separate scoping and resolution, independent of your main container. In this scenario (described here by Bill Pierce) you provide a SubContainer for each tenant, and simply register the components that that tenant needs that are different from the default.

Here’s a simple demonstration:

public void SubContainer_should_get_components_of_parent()
{
    var parentContainer = new WindsorContainer()
        .Register(
            Component.For<Root>().LifeStyle.Transient,
            Component.For<ChildNode>().LifeStyle.Transient,
            Component.For<IGrandChild>().ImplementedBy<GrandChild>().LifeStyle.Transient
        );

    var subContainer1 = new WindsorContainer()
        .Register(
            Component.For<IGrandChild>().ImplementedBy<FirstGrandChild>().LifeStyle.Transient
        );

    var subContainer2 = new WindsorContainer()
        .Register(
            Component.For<IGrandChild>().ImplementedBy<SecondGrandChild>().LifeStyle.Transient
        );


    parentContainer.AddChildContainer(subContainer1);
    parentContainer.AddChildContainer(subContainer2);

    var parentRoot = parentContainer.Resolve<Root>();
    parentRoot.Accept(node => Console.WriteLine("Resolved from parent container: {0}", node.GetType().Name));

    var child1Root = subContainer1.Resolve<Root>();
    child1Root.Accept(node => Console.WriteLine("Resolved from subContainer1: {0}", node.GetType().Name));

    var child2Root = subContainer2.Resolve<Root>();
    child2Root.Accept(node => Console.WriteLine("Resolved from subContainer2: {0}", node.GetType().Name));
}

Which outputs:

Resolved from parent container: Root
Resolved from parent container: ChildNode
Resolved from parent container: GrandChild
Resolved from subContainer1: Root
Resolved from subContainer1: ChildNode
Resolved from subContainer1: FirstGrandChild
Resolved from subContainer2: Root
Resolved from subContainer2: ChildNode
Resolved from subContainer2: SecondGrandChild

I’m creating a parent container and registering three components, Root, ChildNode and IGrandChild. Root depends on ChildNode and ChildNode depends on IGrandChild. I then create two subContainers and register alternative IGrandChild components for each.

I’ve got a little visitor pattern thing going to run some function over each object in the graph so that I output the component types.

When I resolve Root from the parent container, I simply get an object graph with IGrandChild implemented by GrandChild. So my default implementation works as expected.

The really cool stuff happens when I resolve Root from the sub containers. Root is not registered with the sub containers, so they resolve it from their parent (parentContainer). The same goes for ChildNode. But the IGrandChild dependency is satisfied by the sub container’s registration. With this technique you can surgically replace specific dependencies.