Validation as it should be in my eyes

public void Foo(string parameter1, string parameter2)
{
	if(string.IsNullOrEmpty(parameter1))
		throw new ArgumentException("parameter1", "Parameter1 should not be null or empty");
	if(string.IsNullOrEmpty(parameter2))
		throw new ArgumentException("parameter2", "Parameter2 should not be null or empty");

	// Actual method logic
}

Seems familiar? Well it should. I bet that in your current project there is at least one method that looks like this. Do you think that this is a good way of validating input parameters? The honest answer is that this approach is not wrong but it has it’s shortcomings:

  • If the validation logic changes you will have to recompile the solution
  • The validation message is hard-coded
  • If you would like to reuse the validation logic you have a major refactoring session before of you
  • There is bound to be inconsistency in the validation logic across different methods

The main question here is not what is wrong with this approach but how to make it better.

In my experience as a software developer I have seen many implementation of what could be called a validation framework and used many that are already there. Some are good, very good, but lack some basic functionality. What I expect from a validation framework is the following:

  1. Uphold the DBC principle
  2. Have a way of defining the validation logic outside the compiled solution source
  3. Support IOC
  4. Uphold the DRY principle
  5. Extendability
  6. Optional: Provide a fluent interface for validation setup

DBC

Or design by contract is the α and Ω of a good validation framework. If you want to validate something you have to know what to validate. Some years ago Bertrand Meyer developed this concept for his little language called Eiffel. The idea is to write software that doesn’t do more or less than it claims to do. To validate these claims we have the following “tools”:

  • Preconditions: Every routine places a certain set of preconditions that have to be met for the routine to execute.
  • Postconditions: Every routine does something to the world it runs in. And this is the mechanism we use to validate that the effects of the routine are as promised.
  • Class invariants: Basically describes a set of rules that ensure that the object is in a valid state, from the callers perspective.

If a object and its methods adhere to the principles of DBC all callers know:

  • What conditions (states of parameters) must be provided for the method to execute.
  • That if the preconditions are met the method will execute.
  • That the method fill finish. It is something that we take for granted, but the existence of a postcondition ensures that the method will conclude with a positive or negative result.
  • If the method finishes successfully you know exactly what you get.
  • After the method is done executing the object will be in a valid state.

And if you follow DBC to the point you will find out that the calling routine is responsible for the preconditions of the called routine. That is something that is hart to realize in the .NET world but is still a nice idea.

Non compiled configuration

Sometimes you have the luxury to decide what is valid or what is not, you can say that the user name may not be shorter than 5 characters. But at the same user names may not be longer than 255 characters. Why is that? Because of the maximum capacity of the database column. And this is my point. In my experience 80% of validation constrains are imposed on the system, from databases, business rules,… So the last thing you want  is to have the validation logic compiled into the code. For example:

public class User
{
  [RequiredField(Message= "A user name has to be provided")]
  [StringLengthRange(MinLength = 5, MaxLength = 255, Message = "The user name must be between 5 and 255 characters long")]
  public string UserName { get; set; }

  [RequiredField(ResourceKey = "Account/UserNameErrorMessage")]
  [StringLengthRange(MinLength = 8, MaxLength = 255, Message = "The password must be between 8 and 255 characters long")]
  public string Password { get; set; }
}

Lets say that because of popular demand the user name length is extended from 255 to 500 characters. Now you have to open the source code, make your changes, compile and redeploy it to the customer. Thats a lot of work for a simple task. Not to speak of a nasty side effect.

This implies that not only the validation logic is hardcoded but the error messages to. So what do you do if you want to provide a multi-language application? Any ideas? Well to put is in plain words: because you rely on some auto-magic mechanism to validate your objects and produce the error messages on the front-end you just ran into a major problem!

And for those of you that are thinking to use the build in resource capabilities let me tell you that you can’t. Why?

  1. You do not have any clean access to the culture information of the user (the one using the application)
  2. You get a compiler error if you use anything except types and static strings in attributes

So what I want is an external uncompiled, we could call it dynamic, way of configuring the logic. The most popular option is an external XML configuration, like with log4net and nHibernate.

What I want is something like the following:

<validators>
  <validator name="UserNameValidator" base_type="System.string">
    <validator ref="StringNullOrEmpty" />
    <validator ref="Regex">
      <regex>^([a-zA-Z0-9]{6,15})$</regex>
    </validator>
  </validator>
  <validator name="PasswordValidator" base_type="System.string">
    <validator ref="StringNullOrEmpty" />
    <validator ref="Regex">
      <regex>^\w*(?=\w*\d)(?=\w*[a-z])(?=\w*[A-Z])\w*$</regex>
    </validator>
  </validator>
</validators>

<object_validation type="Foo.Person, Foo">
  <invariants>
    <member name="UserName" type="System.string">
      <validator ref="UserNameValidator" />
    </member>
    <member name="Password" type="System.string">
      <validator ref="PasswordValidator" />
    </member>
  </invariants>
<preconditions>
<property name="UserName" direction="set">
      <validator ref="UserNameValidator" />
    </property>
    <method name="SetPassword">
<parameter name="password">
        <validator ref="PasswordValidator" />
      </parameter>
    </method>
  </preconditions>
</object_validation>

Not perfect but it’s a start. Defining the validation like this brings some advantages:

  1. You do not have to change your code to change your validation logic
  2. You can actually reuse validation logic

IOC

Why do we all love and use log4net and hate other frameworks. I think that one reason is that it just works. But the one I want to point out the fact that log4net does not tightly couple with your code! If you want to test your module and ignore the logging you can. And the same is to be expected from the validation. I do not want that my code gets “infected” by a third party framework. I want to put it in a separate part of the application and talk to it when I want and not when the validation things that I should talk to it.

In achieving this goal IOC is more a guideline. If you design your software like it uses a IOC framework you will get exactly the loosely coupled framework you want. And as an added bonus using it with an IOC framework will be a breeze.

It is not my intention to explain the IOC principle here and list all the IOC frameworks out there. So if you are interested in it here is a nice starting point.

DRY

Don’t repeat yourself! Three words that should guide your every key stroke when writing software!

If I am to use a validation framework I want to define all of my validation logic there. ALL OF IT. I do not want to have some additional code somewhere where it could cause trouble later. So if the framework forces me to write a XML configuration I want it to hold all the validation logic!

Basically like with log4net. I define how to log in the XML configuration later I just say that I want to log something and my log messages land where they should.

So if there has to be some validation code written it should be generated out of the XML configuration.

Extendability

There is no framework out there that could cover all the bases. There is not way that your software could handle all that people want it to do. So I want it to be extendabile! I want to validate my custom object with some fancy rule that no one in their right mind would think about. I should be able to make it happen, with minimal effort.

So that is something that is quite important.

Fluent interface

I know that this breaks some earlier requirements. But for sheer usability there is nothing better. And to be honest, as a software developer I know that it is not a hard thing to do. So give me something like

public ValidatorCollection SetUpValidator()
{
  var validators = new ValidatorCollection();

  var stringValidator = new Validator<User>()
                                 .For(u => u.UserName)
                                 .NotNull()
                                 .NotEmpty()
                                 .LongerThan(8)
                                 .ShorterThan(255)
                                 .Maches("^([a-zA-Z0-9]{6,15})$")
                                 .Message("UserName must...");
  // ...

  validators.Add(stirngValidator);

  // ...

  return validators;
}

Breaks my non compiled principle and potentially the DRY principle but is damn easy to use. And I hate it for that. How can something to wrong be so good to use.

This feature is optional but a really, really nice to have.

What now?

Well that is a good question! To be honest I spend quite some time looking at validation frameworks and non of them fulfill all of the points above. So I decided to do something radical.

I will build my own and share it with the world!

I would like to provide something comparable with log4net. Easy to use but immensely powerful! I even spend 5 minutes creating a logo 🙂

valy logo

valy logo

This is still more of a brain child of mine than a clear plan of what I would like to do. So please do leave a comment and tell me what you would like to see. Or even better, join!

You can find the projects homepage here.

As I mentioned earlier this is still in the faze of figuring out what to do so please be gentle.

Thanks for the support up front!