Documentation

Statement of Purpose

The goal of Ensurance is to provide a flexible validation API for production code. Ensurance is used when you need to Ensure that a condition is valid or when a constraint must hold. Typically there is only one way in which we deal with these situations, whatever it may be. Ensurance allows you to change the way your code reacts to failed assumptions.

What does Ensurance provide?

All to often code is written, rewritten, and copied to validate an assumed state. You will see code riddled with lines such as
if( dbConnection == null )
{
    throw new ArgumentNullException();
}
// or ...
if( !File.Exists( fileName ) )
{
    throw new FileNotFoundException( fileName );
}

This is unsightly and and very limiting. Do you really always want to throw an exception?

Why not use Debug.Assert?

The idea with the Trace and Debug asserts is that they are compiled out. Ensurance is meant to stay in your production code, though you may want to change how it reacts.

OK, so how is it used?

The Code

Think of unit testing for production code without being limited to assertion exceptions.
Ensure.IsNotNull( dbConnection );
// or...
Enure.Files.AreEqual( fileOne, fileTwo );

The Flexibility

Ensurance follows an assertion model like NUnit, but the behavior is dynamic. In your code you will initialize a responsibility chain that will determine how Ensurance will deal with broken constraints. For example:
Ensure.SetEnsuranceHandlers( new TextMessageWriter( Console.Out ), new StackTraceWriter( Console.Out ) );

If your code were to call Ensure.IsNotNull( null ); , the TextMessageWriter would write information to the console followed by a stack trace of only your code so that you can see what parts of your code are responsible for the error. The EnsuranceHandlers will act on a failed constraint and always pass the event to its successor.
Say you want to immediately break when your assertion fails, exactly on the line that failed. Let us take a step further and say that you would like to see how the system deals with the assertion failing. You can set up this situation easily;
Ensure.SetEnsuranceHandlers( new ExceptionEnsuranceHandler(), new DebuggerEnsuranceHandler() );

Here the exception will be thrown, but the debugger will be triggered first. Remember, every handler gets it chance. Once you are taken to the offending line of code, your can resume execution and trace how your application responds.

What would a simple application look like using Ensurance?

internal class Program
{
    private static void Main(string[] args)
    {
        TestEnsure();
    }

    private static void TestEnsure()
    {
        try
        {
            Ensure.SetEnsuranceHandlers(
                                                 //new TextMessageWriter( Console.Out ),
                                                 //new StackTraceWriter( Console.Out ),
                                                 //new DebuggerEnsuranceHandler(),
                                                 new ExceptionEnsuranceHandler() );
            FailingMethodCall( null );
        }
        catch (EnsuranceException ex)
        {
            Console.WriteLine( ex );
        }
        Console.ReadLine();
    }

    public static void FailingMethodCall( object val )
    {
        Ensure.IsNotNull( val );
    }
}

What about extensibility?

If you want to always to the same thing all of the time? You can easily extend Ensurance or use one of its built in single responsibility classes.
Ensure.With.Throw.IsNotNull( dbConnection );
Ensure.With.Debugging.Files.AreEqual( imageFile1, imageFile2 );

There are two projects in the samples folder that show how you can extend Ensurance to create classes to do:
            EnsureWithLog.IsNull( args );
            EnsureWithLog.Greater( args.Length, 0, "The number of arguments was not greater than {0}", 0 );
// or...
            Ensure.With.Logging.IsNull( args );
            Ensure.With.Logging.Greater( args.Length, 0, "The number of arguments was not greater than {0}", 0 );
// or...
            EnsureWithLogAndThrow.IsNull( args );
            EnsureWithLogAndThrow.Greater( args.Length, 0, "The number of arguments was not greater than {0}", 0 );

Last edited Oct 13, 2007 at 9:59 PM by idavis, version 12