Monday, January 14, 2008

Resolving Extension Methods

Paul Stovell (author of SyncLINQ) has pointed out another issue with Extension Methods. As he writes:

The problem is the methods are *resolved* at compile time.

Suppose you had this:

void DoStuff(this IFoo foo);

class FooFactory
IFoo Create()

If your factory returns an object that provides its own instance implementation of DoStuff, it WILL NOT be invoked - the extension method will instead. This breaks many of the rules around polymorphism and good OO in general...


In other words, the compiler favours instance methods over extension methods, but only if it can "see" the instance method at compile time.

The reason is simple: currently, resolving an extension method is just a compiler trick, so compile time is the only time when it CAN be done.

But Paul's comment got me thinking. It occured to me that, if my idea about using interfaces was implemented, then it would be possible to properly solve the problem he described. It would work like this:

First, to recap: I suggest that there should be a mapping between extension methods and interfaces. Think of a set of extension methods as an "extension contract". You can make calls on the methods in that contact either by calling intstance methods (on objects which implement the interface) or by extension methods (for objects which do not implement the interface). This is to solve the versioning problem, but it can also be used to solve the problem Paul described.

How? I'll try to illustrate with an example. Imagine that our "extension contract" is called IExtensionContract. It contains two methods, Foo and Bar. We can call Foo and Bar on objects which don't support IExtensionContract, simply by calling them as extesion methods. But, when we call Foo and Bar on objects which DO support IExtensionContract, we want to call the version that is on the object even if we can't tell that the object supports them at compile time. (That's the heart of the issue, right Paul?)

That could be done if the complier worked like this:

Given this code to compile

ISomething s = ...
s.Foo();

The compiler should compile it as if the programmer had written
ISomething = ...
IExtensionContract c = s as IExtensionContract;
if(c == null)
StaticExtender.Foo(s);  // invoke the extension method
else
c.Foo();                // invoke the instance method

This would be possible, if the interface-based versioning solution was adopted, because that solution introduces just enough runtime information about the extension methods - namely the "contract" to which the methods belong. Contrast that to the current situation, where there is no runtime information about extension methods.

Here is the user-authored (i.e. not compiler-generated) code for the example above:
public static class StaticExtender : IExtensionContract 
// "inheriting" from interface here is my suggested addition to the language
{
public static Foo(this ISomething s){...}

public static Bar(this ISomething s){...}
}

public interface IExtensionContract
{
void Foo();
void Bar();
}
Finally, all the suggested logic I have blogged about previously still applies. The compiler still needs to decide, at compile time, whether the call is to a method in the extension contract or to a like-named (but otherwise unrelated) instance method. All that logic still applies as I described it here.

Saturday, January 12, 2008

Readability in Validation

My favourite pattern for validation code is to have one method per validation rule. I think it makes it easier to read and manage the rules.

For instance, I like to be able to write something like this:
[Validate]
protected bool EndDateMustBeAfterStartDate()
{
return EndDate > StartDate;
}
I like to refine the pattern a little, in order to:

(a) Construct error messages based on the method names. That makes the code more concise and encourages good method names. E.g. the failure message from the rule above will be "End date must be after start date".
(b) Allow you to, alternatively, specify dynamically-generated failure messges from within the method body (see below)
(c) Easily specify if the rule is not applicable in a particular situation (again see below).

I've attached some sample code (with tests).

By the way, I once wrote some code to fire rules automatically, whenever a property used by the rule was changed. But that's not included here. In this sample, you have to ask the system explictly to run the rules at a particular time.

Here are some example rules, and the code to call them:
public class Animal
{
...
public string AnimalName
{
get { return _animalName; }
set { _animalName = value; }
}

public int NumberOfLegs
{
get { return _numberOfLegs; }
set { _numberOfLegs = value; }
}

[Validate]
protected Result NumberOfLegsMustBeEven()  
{
return NumberOfLegs % 2 == 0;
}

[Validate]
protected Result MythicalSpeciesAreNotAllowed()
{
if (AnimalName == "Unicorn" || AnimalName == "Dragon")
return Validation.Error("'" + AnimalName + "' is not a real species");
else
return Validation.NotApplicable;
}  

// Note the use of the OR operator here to give a compact syntax for returning a custom error
[Validate]
protected Result NumberOfLegsMustBePlausible()
{
return NumberOfLegs <= 10 || Validation.Error("Your '" + AnimalName +  "' has too many legs");
} 

...
// execute like this
foreach(Result r in Validator<Animal>.ExecuteRulesOn(myAnimal))
if(!r.Pass)

// or, like this, if you don't want to use the generic Validator class
Validator v = Validator.GetInstanceFor(typeof(Animal));
foreach (Result r in v.ExecuteRulesOn(myAnimal))
...