Followup: How to validate a method’s arguments?


A few days ago I and Fredrik Normén had a discussion about argument validation here: http://weblogs.asp.net/fredriknormen/archive/2008/05/08/how-to-validate-a-method-s-arguments.aspx

The discussion got kind of stuck in my head, so I have been thinking a bit more about it.
And today I came up with a solution that I think is both clean and easy to extend.

Fluent Argument Validation Specification

The idea is to transform the value of the argument that should be validated into an object which contains both value and argument name, so that this object can be passed around to different fluent validation methods.
By doing this, we can now add new extension methods for the generic argument class in order to extend our fluent validation API.

A fulent API will let us read and write the requirements just like a specification for each argument.

Here is an example of the consumer:

public static void MyMethod(string someArg,int someOtherArg)
{
    someArg.RequireArgument("someArg")
           .NotNull()
           .ShorterThan(10)
           .StartsWith("Roger");

    someOtherArg.RequireArgument("someOtherArg")
                .InRange(10,100)
                .NotEqual(33)
                .NotEqual(51)
    //do stuff
}

As you can see, we only have to specify the argument name in the require method.
The require method will return an instance of “Validation<T>” which is our generic argument class.

The argument class have no own instance methods, instead we have extension methods which are fluent so that we can call them in a chain.

These extension methods can operate directly on “Validation<T>”,with or without generic constraints.
We can also add extension methods for specific types, like: “Validation<string>”, and thus allow us to validate strings in different ways than other types.

But enough talking, here is the required code to accomplish this:

The implementation of the Validation<T> class:

public class Validation<T>
{
    public T Value { get; set; }
    public string ArgName { get; set; }
    public Validation(T value, string argName)
    {
        Value = value;
        ArgName = argName;
    }
}

The implementation of the Require method:

public static class Extensions
{
    public static Validation<T> RequireArgument<T>(this T item, string argName)
    {
        return new Validation<T>(item, argName);
    }
}

And the implementation of the different validation methods:

public static class ValidationExtender
{
    [DebuggerHidden]
    public static Validation<T> NotNull<T>
    (this Validation<T> item) where T : class
    {
        if (item.Value == null)
            throw new ArgumentNullException(item.ArgName);
        return item;
    }
    [DebuggerHidden]
    public static Validation<string> ShorterThan
    (this Validation<string> item, int limit)
    {
        if (item.Value.Length >= limit)
            throw new ArgumentException(
                  string.Format("Parameter {0} must be shorter than {1} chars",
                  item.ArgName,limit)
                                        );
        return item;
    }
    [DebuggerHidden]
    public static Validation<string> StartsWith
    (this Validation<string> item, string pattern)
    {
        if (!item.Value.StartsWith(pattern))
            throw new ArgumentException(
      string.Format ("Parameter {0} must start with {1}",item.ArgName, pattern)
                                       );
        return item;
    }
    //other validation methos
    .....
}

The [DebuggerHidden] attribute is optional, but it will make your stacktrace look better since it will break in the method that performs the Require call, and not inside the validation methods.

So by using the debugger hidden attribute we can get the behaviour as seen on this screenshot:


 

Enjoy

//Roger

19 thoughts on “Followup: How to validate a method’s arguments?

  1. Pingback: Use constraints instead of argument validation - Fredrik Normén

  2. Excellent!

    Since Fredrik Normén article I have been looking in to easy ways of performing validation, since I must admit I’m one of those who do not always validate all data.

    One thing. What is the performance loss when creating a new validator class each time a method is called?

  3. >>What is the performance loss when creating a new validator class each time a method is called?

    About 13% if you make a naive raw test that just call and validate, w/o any actual method body..

    And almost zero if you have _real code in the method bodies_ of the methods that perform the validation.

    So you will not notice any performance drops if you use this in a business app or framework.

    As soon as an application involves a database , service calls or html rendering(web app), then the overhead of the application itself is so huge that this kind of performance values are completely hidden.
    You can make pretty nasty things in such applications before you get any performance problems.

    And if you need tight optimized loops that should run fast, then I guess you shouldnt be validating much anyway.

  4. Thanks for explaining Roger. One more question. Am I correctly understanding the [DebuggerHidden] attribute, if I say it only works while running the code in Visual Studio’s debugger.

    If an exception is thrown in production code, the stacktrace will still be rooted at the validation method?

  5. Roger,

    I think this it very interesting what you and Fredrik are doing here. Could this grow to a complete Fluent Argument Validation framework?

    >>So you will not notice any performance drops if you use this in a business app or framework.

    The creation of extra objects on the managed heap gives extra pressure on the garbage collector. I agree with you that this extra pressure is possibly unnoticeable in a business app. However, I think you can’t easily state this for a framework. What do you think the impact on the performance of the .NET framework would be, when every public method that does argument validation, created an object on the managed heap for each argument to validate? I think we, as .NET developers, would all be complaining a lot!

    Personally I think maintainable and defensive code are more important than performance tuned code when it comes to business applications. I think the presented API is a great way to improve both maintainability and correctness.

    I hope this could become a fully workable API someday. Maybe you should publish it on CodePlex? I would be happy to help adding validation methods to the API.

    There is one little performance improvement I’d like to propose. Move all the exception throwing code out of the public ValidationExtender methods. This way those validation methods probably will get inlined during JIT-time (because they are so small) and that saves some performance. (I already saw some improvements when I measured this yesterday).

    public static Validation NotNull(this Validation item) where T : class
    {
    if (item.Value == null)
    ThrowHelper.ThrowArgumentNullException(item.ArgName);
    return item;
    }

    I think improving the performance of your fluent argument validation is important, because I think that code isn’t part of your business application; you should make it a framework ;-)

    Another way you theoretically could win some performance is by making the Validation a struct instead of a class. This way you won’t create extra objects on the heap. This, together with the inlining explained above, should lead to a validation that is as fast as a normal ‘if (arg == null) ThrowHelper.Throw(“arg”)’ construction.

    I said “theoretically”, because I did some performance tests and performance actually degraded when making the Validation struct. Bummer!

  6. Interesting post Steven. The performance test you did (class vs. struct), could the result you are seeing be due to the fact that the JIT is inlining the classes and not the structs?

  7. This was really nice!

    I got me thinking, what if you used could use a method interceptor and check for validation attributes?

    I was able to get this to work:

    public interface IRegistrationService
    {
    void Register([NotNull] string name, [InRange(5, 10)] int value);

    void Register([NotNullOrEmpty] string name);
    }

    You have to use a proxy generator though, and it is only applicable to interface and virtual functions. And the performance is not optimal. I wish the concept of a method interceptor was incorporated into the CLR :)

  8. Hi Torkel,
    Have you ever looked at my AOP framework NAspect?

    I’ve got a DbC sample in there that does exactly the same as you :-)

    Snip:
    public virtual void ReceiveAString(int abc,[NotNull]string def)

    Snip:
    [NotNull] //your version with return: is nicer
    public virtual string ReturnAString(int i)

    Snip:
    public object HandleCall(MethodInvocation call)
    {
    ParameterInfo[] parameters =call.Method.GetParameters();

  9. That is nice, I haven’t tried NAspect, I figured someone else had done it :)

    I have only used Castle Dynamic Proxy / Windsor to handle AOP. I find myself using interceptors more and more and should probably move to a framework that offers more out of the box AOP support :)

  10. Also, Argument validation is not a very good AOP candidate IMO.

    While it is 100% true that validation is a crosscutting concern, you still have to specify somehow _how_ the arguments should be verified _per usecase_.

    You will still have to add some sort of meta data to your methods.

    So the benefit is small while you add alot of extra complexity to your app.

    If you write “[NotNull]arg” outside of the method , or “arg.NotNull()” inside it doesnt really matter, you are still expressing the same thing.

    The AOP version ofcourse come with some benefits, eg you don’t have to specify the arg name and it can be applied to multiple return statements etc.

    But all in all, very small benefits for a quite high cost, unless your app already relies on AOP for other tasks.

    Also, multiple attributes per argument makes the code somewhat hard to read.

  11. I agree that it hurts readability to some extent, and doesn’t offer that much of more value to compared to arg.NotNull() (except that you can define the attributes on interfaces and have them checked on each implementation).

    But the biggest problem is that it can only be applied to interface and virtual functions, and you have to construct the object using a proxy generator (if the class is a component in an IoC container this is not so big of a problem). Another problem could be performance.

    But it’s a nice idea, maybe not the most practical with the current limitations for method interception :)

  12. Pingback: Argument validation framework released « Roger Alsing Weblog

  13. Pingback: Fluent Argument Validation - Colin's Blog

  14. Pingback: Algumas Idéias » Blog Archive » Fluent Argument Validation

  15. Pingback: Argument Validation using C# 3.0 extension methods « JBloggin’

  16. Hey Roger,

    I loved this post. I came across it while doing some research on an idea I had to remove a bunch of tedious code that I found myself writing over and over again to validate arguments. I started playing around with your code and made some changes that I thought I would share in case others might find it useful.

    namespace ArgVal
    {
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Linq;
    using System.Linq.Expressions;

    public static class ValidateThat
    {
    public static Argument Argument(Expression<Func> arg)
    {
    return new Argument(arg);
    }
    }

    public sealed class Argument : IHideObjectMembers
    {
    [DebuggerNonUserCode]
    internal Argument(Expression<Func> arg)
    {
    switch (arg.Body.NodeType)
    {
    case ExpressionType.MemberAccess:
    this.Name = ((MemberExpression)arg.Body).Member.Name;
    break;
    case ExpressionType.Parameter:
    this.Name = ((ParameterExpression)arg.Body).Name;
    break;
    default:
    throw new ArgumentException(“Expression body must be of type MemberAccess or Parameter.”, “arg”);
    }

    this.Value = arg.Compile().Invoke();
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public TArg Value { get; private set; }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public string Name { get; private set; }
    }

    public static class ArgumentValidationExtensions
    {
    [DebuggerNonUserCode]
    public static Argument IsNotNull(this Argument arg)
    where T : class
    {
    if (arg.Value == null)
    throw new ArgumentNullException(arg.Name, “Cannot be null.”);

    return arg;
    }

    [DebuggerNonUserCode]
    public static Argument IsNotEmpty(this Argument arg)
    {
    if ((arg.Value != null) && (arg.Value.Length == 0))
    throw new ArgumentException(“Cannot be an empty string.”, arg.Name);

    return arg;
    }

    // Additional validation extensions omitted for brevity
    }
    }

    I removed comments and condensed the code for brevity. The IHideObjectMembers interface is also omitted but can be seen here . It along with the EditorBrowsable attributes on the Value and Name properties help to make the fluent API cleaner by removing from intellisense non-validation methods. Hopefully, in my copying and condensing I didn’t screw anything up so that this code could be copied directly and played with.

    Note that the EditorBrowsable attribute only works if compiled into an assembly and referenced in some other consuming project. This was killing me yesterday until I found this .

    For my purposes, I like how this came out. I like using the Linq expressions for strongly-type references to the arguments therefore removing the need for strings and starting with the static ValidateThat class as opposed to an extension method that sort of “shows up everywhere” once brought into scope with a using declaration.

    Thoughts?

    Also, I saw that one or two people talked about making this a published API on CodePlex or Google Code. I think it is a cool idea and would start it if anyone is interested. Anyone have a cool name in mind?
    NArg anyone? :)

    Again, thanks for the great idea. I plan on using it a lot.

  17. Pingback: Janga – A Validation Framework with a Fluent API « ActiveEngine

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s