views:

166

answers:

6

Validating Primitive Arguments and "Complex Data"

Validating Arguments

When writing a method, arguments should be validated first before any operations are performed. For example, let's say we've got a class representing people:

public class Person
{
    public readonly string Name;
    public readonly int Age;

    public class Person(string name, int age)
    {
     this.Name = name;
     this.Age = age;
    }
}

What's wrong with this Person class? name and age aren't validated before their values are set as fields of Person. What do I mean by "validated?" Both argument should be checked that their values are acceptable. For example, what if name's value is an empty string? Or age's value is -10?

Validating the arguments is performed by throwing ArgumentExceptions or derived exceptions when the values are unacceptable. For example:

public class Person(string name, int age)
{
    if (String.IsNullOrEmpty(name))
    {
     throw new ArgumentNullException
      ("name", "Cannot be null or empty.");
    }

    if (age <= 0 || age > 120)
    {
     throw new ArgumentOutOfRangeException
      ("age", "Must be greater than 0 and less than 120.");
    }

    this.Name = name;
    this.Age = age;
}

This properly validates the arguments Person's constructor receives.

Tedium ad Nauseum

Because you've been validating arguments for a long time (right?), you're probably tired of writing these if (....) throw Argument... statements in all of your methods.

What can we do to avoid writing String.IsNullOrEmpty a bazillion times throughout your code?

A: 

Code Contracts

Greg Beech
+5  A: 

You can look into Code Contracts in .NET 4.0.

You may also want to look at the FluentValidation Library on CodePlex if you don't want to wait for code contracts.

Ultimately, you still need to put the rules that govern argument values somewhere - it just a matter of deciding whether you prefer an imperative style (e.g. string.IsNullOrEmpty) or a declarative one.

Validating your inputs as is a key practice for writing solid code - but it certainly can be repetitive and verbose.

LBushkin
What about Code Contracts should I look at?
JamesBrownIsDead
CC provides a concise syntax for expressing constraints and preconditions for methods. It also defines a standard model for reporting violations of those constraints using exceptions. While it doesn't eliminate the need to think about and define preconditions, it helps express them in a consistent manner in your code. Also, if you're using VSTS, many of the constraints can be statically verified (at compile time) helping you detect problems when you write the code, rather than run it.
LBushkin
A: 

I'll give a solution in the D programming language. I don't know how powerful C# generics and variadics are because I don't use C#, but maybe you could adapt this:

void validate(T...)(T args) {  // args is variadic.
    foreach(arg; args) {  // Iterate over variadic argument list.
        static if(isSomeString!(typeof(arg))) {  // Introspect to see arg's type.
            if(arg.isNullOrEmpty) {
                throw new ArgException(
                    "Problem exists between keyboard and chair.");
            }
        } else static if(isOtherTypeWithBoilerPlateValidation!(typeof(arg))) {
            // Do more boilerplate validation.
        }
    }
}

Usage:

class Foo {
    SomeType myMethod(T arg1, U arg2, V arg3) {
        validate(arg1, arg2, arg3);

        // Do non-boilerplate validation.

        // Method body.
    }
}
dsimcha
+2  A: 

You may be helped by using more complex types rather than primitives.

For example, if you take the time to define something like a PersonName class, you can have the validation there, and you don't have to keep validating it on every other object that needs to have a name on it.

Obviously this is only going to help the problem if you have multiple objects that use the same field types.

TM
+1  A: 

You can try using the Castle Validation Framework => http://www.castleproject.org/activerecord/documentation/v1rc1/usersguide/validation.html

OR

You can use a simple validation framework that I created. Both the frameworks uses Attribute based validation. Check out the link below:

http://www.highoncoding.com/Articles/424%5FCreating%5Fa%5FDomain%5FObject%5FValidation%5FFramework.aspx

azamsharp
+1  A: 

There are options based on Postsharp. code-o-matic is one of them. It lets you write code like this:

public class Person(
    [NotNull, NotEmpty] string name,
    [NotNull, NotEmpty] int age
)
{
    this.Name = name;
    this.Age = age;
}

I use this every day at work.

Antoine Aubry
God I wish this was in the language proper. If I have to validate an argument for a simple condition (like null) again I'm gonna shoot someone!
orj