Thursday, 21 August 2008

A less fragile way to invoke a generic method with a dynamic type argument

A fellow Fluent NHibernate contributor Andrew Stewart called out for ideas on how some of his code could be refactored and if you've programmed with me you will know that I jumped at the chance. Here is the rather unfortunate code:

var findAutoMapMethod = typeof(AutoMapper).GetMethod("MergeMap");
var genericfindAutoMapMethod = findAutoMapMethod.MakeGenericMethod(type);
genericfindAutoMapMethod.Invoke(autoMap, new[] { mapping });

Here is what Andrew wants to do (sort of):

Type type = GetSomeType();
autoMap.MergeMap<type>(mapping);

This is illegal because you can't pass a type instance as a type parameter to a generic method. For example, you can't declare a list of strings like this:

List<typeof(string)> stringList;

Andrew is calling a generic method but he doesn't know the type argument at compile time. The only way around this is reflection, and we all know that reflection is fragile - if someone changes the MergeMap method to be called MergeMapping, the code will compile and fail at runtime (hopefully when your unit tests are executed!). Fortunately, there is a way to make this block of code significantly less fragile. To do this, I'm going to rely on the handy ReflectionHelper that is part of the Fluent NHibernate code base. Here's the method I'm going to use

public static MethodInfo GetMethod(Expression<Func<object>> expression)
{
 MethodCallExpression methodCall = (MethodCallExpression)expression.Body;
 return methodCall.Method;
}

So if I pass this baby a lambda expression containing a method invocation, it gives me the corresponding MethodInfo. Sweet! Lets use it

var templateMethod = ReflectionHelper.GetMethod((AutoMapper a) => a.MergeMap<object>(null));

Notice the type argument of 'object' ? Its a placeholder. The parameter 'null' is also a placeholder. What you need to realise is that we are not going to -execute- the code in that lambda. The reflection helper is going to inspect it and give us a MethodInfo to work with. Before we can invoke the MethodInfo, we need to replace the first placeholder, which is why I have called this one templateMethodInfo. Lets replace the placeholder:

var realMethodInfo = templateMethod.GetGenericMethodDefinition()
                     .MakeGenericMethod(type);

The GetGenericMethodDefinition call lets you obtain a MethodInfo for an unbound version of MergeMap. Once the method is unbound, we supply the particular type argument we want, being 'type' in this case. MakeGenericMethod takes an array of types so this process would also work fine for a generic method that has more than one type argument. To further illustrate this process, here is another example:

public static void DoSomething<T, U>() { }
...
static void Main(string[] args)
{
 Action doSomethingAction = DoSomething<object, object>;
 MethodInfo info = doSomethingAction.Method;
 Console.WriteLine(info);
 info = info.GetGenericMethodDefinition();
 Console.WriteLine(info);
 info = info.MakeGenericMethod(typeof(string), typeof(int));
 Console.WriteLine(info);
 Console.ReadLine();
}

OUTPUT: Void DoSomething[Object,Object]() Void DoSomething[T,U]() Void DoSomething[String,Int32]()

Getting back to the task at hand, we can now invoke realMethodInfo, but we must be sure to pass the original intended argument 'mapping':

realMethodInfo.Invoke(autoMap, new[] { mapping });

And thats it! Now if MergeMap is renamed, the lambda body will be updated accordingly by the refactoring tools. Now this code is still fragile because if another type argument is added to MergeMap, this code won't fail until runtime. Lets specifically check for this case and throw an appropriate exception. Lets also wrap it all up in one nice convienent method:

public static class InvocationHelper
{
 public static object InvokeGenericMethodWithDynamicTypeArguments<T>(T target, Expression<Func<T, object>> expression, object[] methodArguments, params Type[] typeArguments)
 {
     var methodInfo = ReflectionHelper.GetMethod(expression);
     if (methodInfo.GetGenericArguments().Length != typeArguments.Length)
         throw new ArgumentException(
             string.Format("The method '{0}' has {1} type argument(s) but {2} type argument(s) were passed. The amounts must be equal.",
             methodInfo.Name,
             methodInfo.GetGenericArguments().Length,
             typeArguments.Length));

     return methodInfo
         .GetGenericMethodDefinition()
         .MakeGenericMethod(typeArguments)
         .Invoke(target, methodArguments);
 }
}

And call it:

InvocationHelper.InvokeGenericMethodWithDynamicTypeArguments(
             autoMap, a => a.MergeMap<object>(null), new[] { mapping }, type);

Ok so its certainly not as clear or robust as:

autoMap.MergeMap<type>(mapping);

But the former has the advantage of actually COMPILING, while the latter does not.

My first open source project

A few weeks ago, I joined an open source project that was just starting up. Its called Fluent NHibernate and provides an alternative to XML based or attribute based mapping of NHibernate domain objects. The project owner James Gregory does a much better job of explaining it than I could.

Why am I only mentioning it now? Well during the first week I was too busy trying to get up to speed and make a useful commit to blog about it. As for the last couple of weeks, I've been holidaying in France and Italy and its been hard enough just keeping up with my RSS and mailing lists.

It has been a great experience so far. The other contributors are really friendly and smart, and I am impressed by the sheer volume (and quality) of work being performed. I'm learning how to use Subversion and really missing continuous integration (yes I already broke the build, managed it on my 2nd commit).

Incidentally, this is my first post using Windows Live Writer. It seems nicer than the Blogger web interface.

Sunday, 8 June 2008

ASP.NET MVC with Visual Web Developer Express

I decided to spend some time playing with ASP.NET MVC this weekend but the install wasn't as straightforward as I would have liked. I do not have Visual Studio 2008 so I've been relying on the express editions, and this somewhat complicated the process. Scott Guthrie's post mentions that Visual Web Developer Express 2008 does not support ASP.NET MVC preview 3 unless you install the SP1 Beta. Unfortunately, the link he provides in that post points to a post about the Visual Studio 2008 SP1 Beta, which kept giving me the following message when I ran it:

Microsoft Visual Studio 2008 SP1 (Beta) does not apply, or is blocked by another condition on your system. Please click the link below for more details.
I googled a bit and tried a few things and eventually discovered that there is a different service pack for the express editions: Visual Studio 2008 Express Editions Service Pack 1 Beta. No wonder I was getting that error message - I do not have any Visual Studio 2008 products installed! The existence of a separate service pack makes perfect sense and is pretty obvious if you think about it. Beware the dangers of mechanically clicking links and googling without thinking! The MVC install went smoothly once I installed the Express SP1 beta.

Thursday, 29 May 2008

Ayende's weird code

I spent the better half of yesterday evening playing with some code that Ayende posted. He wanted to make this compile:

public interface IDuckPond
{
    Duck GetDuckById(int id);
    Duck GetDuckByNameAndQuack(string name, Quack q);
}

IDuckPond pond = null;
pond.Stub( x => x.GetDuckById );
pond.Stub( x => x.GetDuckByNameAndQuack );
My first reaction was WTF! I didn't understand at all what he was getting at, but obviously he was making sense to some people, as the meaningful (but initially over-my-head) comments were quickly piling up. Lets take a look. The interface definition is completely standard, nothing out of the ordinary at all. The weird bit is definately this Stub method. It appears to be a void method that accepts a lambda expression as its only parameter. But hang on a sec, lets forget the lambda expression for a second; this method isn't declared on the IDuckPond interface, and aren't we going to get a null reference exception anyway? Well, not if Stub is an extension method. Now its certainly unclear to me how Ayende was going to do anything meaningful within the extension method given that you can't use the ref or out keywords on the target of an extension method so you are still gonna be stuck with pond = null after the first stub call returns, but nevermind that. So the extension method is going to look something like this:
static class StubExtender
{
    public static void Stub(this IDuckPond pond, SOME_LAMBDA_THINGY)
    {}
}
Where SOME_LAMBDA_THINGY is obviously the lambda expression parameter bit. So what goes there? Well, lets take a look at the first lambda expression that gets passed to Stub:
x => x.GetDuckById
This certainly had me puzzled at first. He's not calling GetDuckById here, because there is no argument.. so what's going on? Thinking about it a bit I realised that the x.GetDuckById is a delegate, which means that the parameter to the Stub method is a function that returns a function. Brain starting to hurt yet? If so, you must be a functional programming newbie like me. Having made this realization, it was pretty quick to get the code compiling. I defined delegates for the two methods on IDuckPond:
delegate Duck GetDuckByIdDelegate(int id);
delegate Duck GetDuckByNameAndQuackDelegate(string name, Quack quack);
And then two overloads for the stub method:
public static void Stub(this IDuckPond pond, Func<IDuckPond, GetDuckByIdDelegate> func) { }
public static void Stub(this IDuckPond pond, Func<IDuckPond, GetDuckByNameAndQuackDelegate> func) { }
Okay, so the first overload takes a function that takes an IDuckPond and that returns a function with GetDuckById's signature. The second overload does the same thing but its parameter is a function that returns a function with GetDuckByNameAndQuack's signature. I quickly realised that I don't actually need the explicitly declare delegates, because I can just use the framework delegate Func, which I was already doing anyway. So the delegates got deleted and the overloads became this:
public static void Stub(this IDuckPond pond, Func<IDuckPond , Func<int, Duck>> func) { }
public static void Stub(this IDuckPond pond, Func<IDuckPond , Func<string, Quack, Duck>> func) { }
So this was better, but certainly not perfect. It was obvious that Ayende was looking for a general solution. The first generalization was simple.. make the stub method generic on the extension target:
public static void Stub<T>(this T obj, Func<T, Func<int, Duck>> func) { }
public static void Stub<T>(this T obj, Func<T, Func<string, Quack, Duck>> func) { }
The cool thing about this is that I didn't have to change the calling code at all. Specifically, I don't have to call pond.Stub<IDuckPond>(etc) - why? Because the compiler does generic parameter inference; it is able to determine that the type T is IDuckPond because we are passing in an IDuckPond as the first argument. But obviously this is still not ideal because as you add new methods to your interfaces, you will need to add the appropriate Stub overloads. You could probably code gen them, but code generating just for the sake of nice syntax seems to be taking things a bit far. I wanted to see if I could come up with anything nicer, and some of the comments in the thread gave me some ideas. This one is okay:
IDuckPond d = null;
d.Stub(x => (Func<int, Duck>)x.GetDuckById);
d.Stub(x => (Func<string, Quack, Duck>)x.GetDuckByNameAndQuack);
    
static class StubExtender
{
   public static void Stub<T, U>(this T obj, Func<T, U> func) { }
}
At least this way we can get by with just one definition for Stub, though at the cost of adding some casts. Now why did I have to add those awful casts? Well I modified the Stub method to be generic, but the compiler can't infer the generic parameter U like it is with T. Why? Lets say that IDuckPond had a third method, an overload of GetDuckById:
interface IDuckPond
{        
    Duck GetDuckById(int id);
    Duck GetDuckById(object o);
    Duck GetDuckByNameAndQuack(string name, Quack quack);
}    
Now when we say x.GetDuckById, its unclear which overload we are referring to, and its important because the delegates would have different signatures. As a result of this fact, the compiler cannot infer the type, so you have to give it explicitly, by casting. Some other neat alternatives were suggested by Jacob Carpenter, you can find those in the comment thread for Ayende's post if you are interested. He's doing something tricky with the default keyword, some investigation is in order methinks. Unfortunately there does not appear to be a perfect solution. You can't get away with the exact code that Ayende specified without writing or generating all the required overloads. I really enjoyed this little challenge, its reminded me that I'm not as good with C# as I would like to think, and instilled me with the urge to do more weird stuff. Expect more posts filled with angle brackets!

Thursday, 22 May 2008

The Mythical Man-Month

Phew, has it already been a month since my last post? There's no doubt about it, GTA IV is to blame. In any case, I haven't been slacking off completely. I just finished reading the rather short and positively ancient The Mythical Man-Month: essays on software engineering by Fred Brooks. This book is considered to be one of the classics. It appears in "must read" lists all the time, and is constantly references by software bloggers around the world.

Originally published in 1975, this book is older than me. I'm reading the 20th anniversary edition which has some added chapters, but the original contents are left as they were - and it sure does show. The book is more about software management than engineering and if offers several valuable ideas, but its also full of discussion that is simply not at all relevant to software engineering today.

The book makes the point that you can't rush software. Doubling your staff will not halve your schedule, and adding manpower to a late software project will probably just make it later. It tackles this concept that men and months are not interchangeable from a number of different angles, and while I consider this idea to be blindingly obvious today, I can appreciate it might not have been quite that way 33 years ago. The 20th anniversary edition contains the "No Silver Bullet" essay which was written about a decade after the first printing of the book. This essay claims that it is unreasonable to expect that any single technological or methodological advance will deliver an order of magnitude improvement to software productivity. Developing software is an inherently difficult complex process, and we can chip away at the difficulties from many different angles, and perhaps achieve order of magnitude improvements through combination of many tools and techniques, but there is no discovery waiting around the corner that will improve our software development productivity by a factor of 10.

I think these ideas are worth reading about, and the book has certainly broadened my perspective and given me insight to how people thought about software development many years ago. However, that said I am reluctant to recommend this book. MUCH of it talks about the practicalities of software development circa 1975 - so its filled with arcane meaningless terms from an era long gone. I couldn't help but laugh at the idea of embedding documentation into code having the downside that "you have to store more characters". I'm now wishing I was taking notes as I read because there were some real whoppers in there, stuff that really makes me appreciate how far we've come. But while some of it was funny, most of it was just snore worthy.

We need a modern replacement for this book. A text that communicates some of the old but worthwhile ideas along with some the new, such as iterative development. A text that I could give to someone else and not have them hand it back upon the first mention of some obscure mainframe operating system that I or they haven't heard of. And while I'm at it: a text that does not make the assumption of the existence of this abstract concept of "God" several times would also be nice - there is no place for that sort of thing in a software text. The man-month ain't the only concept mentioned in this book that I consider to be mythical.

Maybe such a book does exist, and I just don't know about it yet. If you think you've found it, be sure to let me know!

Tuesday, 22 April 2008

Domain Driven Design (the book)

I just finished reading Domain Driven Design: tackling complexity in the heart of software by Eric Evans. This is a book that was recommended to me years ago but I was lazy and ignored the advice - and what good advice it was. Hopefully you are familiar with the concept of a domain model. Implementing a domain model is by far my preferred technique for dealing with business rules in software, probably because so much of it leverages the strengths of object oriented programming (and don't get me started about how much I love OO). The thing about domain models however, is that getting one up and running is only half the battle. I am big fan of the Martin Fowler book Patterns of Enterprise Application Architecture and much of it deals with accomplishing this task. But the thing is, there are already plenty of object-relational mappers avaliable, both commercial and free. Given this fact, its probably incorrect of me to refer to technical aspects of using a domain model as "half the battle" as it should make up a far smaller proportion. The real battle is putting a domain model to work, leveraging its strengths and guarding against anaemia. Designing a domain model of true value is no easy task and it is this particular problem that Evans focuses on in DDD. I really enjoyed the first half of this book, being the two sections Putting the domain model to work and The building blocks of a model driven design as I found then easy to follow and very relevant to the work I am doing. Some of the concepts described were familiar and worth reinforcement, but several were completely new. The second half of the book consists of the sections Refactoring towards deeper insight and Strategic design. I found these sections a bit more uneven than the first, and particularly dry in places. Ever caught yourself and realised that your eyes scanned the last half a page without any of it actually sinking in? This happened to me more than a few times, but I think its as much my own fault as it is Eric's. Putting aside these complaints, the second half of the book is still a very worthwhile read as it introduces many valuable concepts. Its probably worth mentioning that there is not a great deal of code in this book as it is much more concerned with theory than with the hands-on practicalities of developing with a domain model. I can recall a few instances where the book describes a mechanism that made a lot of sense, but it was not entirely clear how I would actually go about implementing it. I am considering picking up a copy of Applying Domain-Driven Design and Patterns by Jimmy Nilsson in the hope it might help fill in some of the gaps. It occurs to me that there might have been a better way to approach the topic of DDD and it might have made Evans a bit more $$. If you take the first two sections of the book and add a few choice selections from the remaining half, you've got an excellent text for introducing developers to domain modelling. You could hand a developer that wasn't experienced with using domain models a 200 page text and they would come back in a few days excited and with a firm knowledge foundation. The majority of the second half of the book consists of material that is more relevant to a developer in a leading or mentoring role and this would easily fit in a follow up, "advanced" book. But don't let my theories on how the material might have been better packaged distract you, because DDD is still a really good book. A few years ago, when I was reading CLR via C# by Jeffrey Richter, I felt kind of embarrassed that I had been doing all this .NET development without much of a clue of what was going on. Reading DDD made me feel much the same way about building applications that use domain models.

Wednesday, 16 April 2008

RSS

RSS stands for Really Simple Syndication and is basically about recording information about updates to a website in a structured format. What you actually need to know about RSS is that most websites these days have RSS feeds and this means that you can do alot of web browsing from within an RSS reader. I use Google Reader because it works via a browser so I can access it from home, work, or my mobile phone and they all stay in sync. RSS is amazing. I thought it was cool when I first discovered it years ago because it meant I didn't actually have to go to my favourite sites to see if they had been updated. And yes, fundamentally, years later, that is still all I use it for. But the really important difference is that initially, I used it to make sure that I didn't miss a Penny Arcade comic while now I use it to plug my brain into lots of really smart people's brains (and also never miss a PA comic). Steve Yegge. Paul Graham. Reginald Braithwaite. These guys are brilliant. I just bought Reg a Darkhorse double espresso via his handy donation link and I would be doing the same for Steve if he made it similarly easy (Paul Graham doesn't need my money, his brilliance has already brought him fat wads of cash). I discovered these names via the ever growing torrent of information that hits in me in the face every morning, noon and night (yep, my brain needs its breakfast, lunch and dinner the same way my body does). There are many other great bloggers that I subscribe to, but the above 3 are special because they are inspirational. Their writing has changed the way I think of myself, my work, and my future. I have struggled in the past to come up with a singular example of why Steve's writing is so great and this evening I went through the same process with Reg. These people are inspirational because they each have their own particular perspective on software development and these perspectives are refined, logical, and exciting. Furthermore, these perspectives are communicated through the aggregate of their writing, rather than any individual piece. Much of my effort to generalize is RSS assisted. I have found the programming sub-reddit to be especially useful as it is focused on less common programming languages such as Ruby, Python, Lisp, Haskell, etc rather than the heavyweights (.NET and Java). My RSS subscription count has probably doubled since I discovered Reddit - its an excellent source of worthwhile blogs. The world wide web has had an incredible influence on my life and RSS has significantly changed how I consume the web's content. Do you ever stop to wonder "gee, how on earth did we ever do anything without the internet"? Well now I'm wondering how I ever got by without RSS.