*IMPORTANT NOTE* This project was started just before Microsoft 
announced that CodeContracts would be incuded as part of .Net 4.0
So there are now (or soon will be) much better ways to handle code contracts in C#. 

I have left this project here as a reference, but do not intend to develop it further. 
If you are interested in CodeContracts I suggest you look in to 
Microsofts Code Contracts in .NET 4.0 (it's very powerful.)

Also, the technique used by ContractDriven.NET to evaluate invariants was to use a 
message sink from .NET remoting (but this requires your object inherits from 
MarshalByRefObject, which many people (including myself aren't particularly happy with) 

However, if you are interested in an alternative. I would suggest you take a look at PostSharp 
(an Aspect Oriented Programming Framework for C#) , which provides a very elegant way of 
injecting code before and after method calls (and handling exceptions)

Thank you and goodnight,

Chris.

ContractDriven.NET

"Fail Fast, Fail Cheap, Be Lazy. The greatest inefficiencies come from solving problems you will never have."

Design By Contract helps developers build high-quality reliable code by validating object behaviour at runtime. Whilst this is built in to languages such as Eiffel and Ada, the .NET Framework provides no direct support for contracts out of the box. The ContractDriven.NET library brings Contract Driven Development to the Microsoft.NET platform. The library is easy to use and provides simple methods for designing contracts in to CLR compliant code (such as C# or VB.NET).

This document contains the following sections:
  • What is Contract Driven Development?
  • Getting Started
  • Overall Design Summary
  • Future Direction and how to contribute

What is Contract Driven Development?

Contract Driven Development (CDD) is closely related to Test Driven Development (TDD). Both are complimentary techniques for improving the quality and reliability of software. Test Driven Development uses unit tests to examine a components' behavior via its' public interface, treating each component as a black box. TDD guarantees that when given specific test data a method behaves as expected. If it does not behave as expected, your unit tests fail. This provides rapid feedback if a change in code results in contractually incompatible behavior. However, testing can only ever prove the existence of defects. It cannot prove their absence. This is where contracts become useful.

Contract Driven Development guarantees that given any valid data a method behaves as expected. It describes how the component parts of the system collaborate. "Client" and "Supplier" classes agree a "contract" (enforced by the supplier class) which defines different types of agreements:
  • Preconditions - things required of the calling client on method entry.
  • Postconditions - things guaranteed to have been performed by the supplier on method exit.
  • Invariants - things that must remain unchanged (within agreed boundaries) throughout the lifetime of an object.

ContractDriven.NET also includes support for value tracking which in turn enables loop invariant/side-effect checking. Unlike unit tests, contract assertions remain in deployed code actively guaranteeing contract agreement as the program runs. Following the Fail Fast design principle, as soon as an agreed contract is broken ContractDriven.NET will throw a ContractException.

Building Bug-free O-O Software: An Introduction to Design by Contract. provides an excellent introduction to Contract Driven Development.

ContractDriven.NET is Licenced under the Apache Licence (v2.0), and so is free to use in open source, personal and commercial projects. If you would like to help improve the project, please feel free to join in!

Getting Started

Introduction

Before using ContractDriven, in order to validate input parameters passed to a method, you would have had to write something similar to the following code...

void InsertStockItem(string itemName, int quantity)
{
    	if (string.IsNullOrEmpty(itemName))
	{
	      throw new Exception("Parameter was null");
	}
	
	if (itemName.Length > 10)
	{
      		throw new Exception("itemName must be 10 characters or less.");
	}
	
	if (quantity < 0 || quantity > 150)
	{
      		throw new Exception("value must be between 0 and 150.");
	}

	//and so on.
 
}

ContractDriven.NET enables you to write more concise code such as...
void InsertStockItem(string itemName, int quantity)
{
 	Require(Assert.IsNotNullOrEmpty(name));
	Require(Assert.IsInRange, name, 0, 10));
	Require(quantity < 0 || quantity > 150);
	//and so on.

}
or in VB
Public Sub InsertStockItem(ByVal newString As String, ByVal newInt As Integer)

	Require(Assert.IsNotNullOrEmpty(name))
	Require(Assert.IsInRange, name, 0, 10))
	Require(quantity < 0 || quantity > 150)
	'and so on
End Sub

However, this is only a starting point serving as an illustration of very basic assertions. unlike most other DbC implementations for the .NET framework, in addition to allowing you to apply
assertions within individual methods (such as the above example), ContractDriven.NET provides support for invariant assertions (using delegates) so that you can monitor the integrity of your
class throughout its' lifetime.

Setting up a class to use Contracts

First, download, compile ContractDriven.NET and reference the ContractDriven.dll in your application. Next, import the ContractDriven namespace and inherit your class from ContractBoundObject. You're now ready to go!

C#
//Import the ContractDriven Namespace
using ContractDriven;
 
namespace ContractExample
{
    //Inherit from ContractBoundObject
    class ExampleClass : ContractBoundObject
    {
 
    }
}

VB.NET
'Import the ContractDriven Namespace 
Imports ContractDriven
 
Namespace ContractExample
 
    'Inherit from ContractBoundObject
    Class ExampleClass
        Inherits ContractBoundObject
 
    End Class
End Namespace

ContractBoundObject makes the contract management sub-system available to your object. (Note: ContractBoundObject automatically checks class invariant assertions for you. However, if you're interested in performance tuning you may want to implement your own optimised invariant checking. You can use the source code as a reference if you want to see what's going on behind the scenes.)

Writing pre and post-condition checks (The Require/Ensure pattern)

A precondition is a condition that must be true before a section of code is executed, and a postcondition is a condition that must be true after a section of code has been executed. These constructs are built in to languages such as Eiffel and ADA using 'require'/'ensure' and 'pragma Precondition '/'pragma Postcondition' respectively, but .NET does not provide such constructs as part of the core framework. ContractDriven.NET uses the Require and Ensure terms (as these are more concise). If a 'Require' assertion is broken, it means the client is at fault. If an 'Ensure' assertion is broken, it means something has gone wrong with the supplier class.

Preconditions allow you to extend parameter contrainst beyond simple type constraints. For example, a method parameter may specify 'Int32', but a Precondition can constrain this to be between 100 and 200 and specifically not 107 for example.

Postconditions ensure that code has performed as required. A common postcondition is a guarantee that number not negative for example.

Pre and Post conditions are written using the "Require()" and "Ensure()" methods. Both of these methods have the same signatures and can accept any boolean assertion and a description of the assertion. For example... Require(x > 0, "x must be a positive number");

ContractDriven.NET also provides standard Assertions for range checking and null checking. You can pass one of these checks as a parameter to either method. For example... Require(Assert.IsInRange(y, 0, 100), "y must be between 0 and 100");

C#
using ContractDriven;
 
namespace ContractExample
{
    class ExampleClass : ContractBoundObject
    {
        private int _myInt;
        private string _myString;
 
        public void SetXandY(int newInt, string newString)
        {
            Require(Assert.IsInRange(newInt, 0, 100));
            Require(Assert.IsNotNullOrEmpty(newString));
 
            _myInt = newInt;
            _myString = newString;
 
            Ensure(_myInt == newInt);
            Ensure(_myString == newString);
        }
        
 
    }
}

VB.NET
Imports ContractDriven
 
Namespace ContractExample
 
    Class ExampleClass
        Inherits ContractBoundObject
 
        Private _myInt As Integer
        Private _myString As String = String.Empty
 
        Public Sub SetXandY(ByVal newInt As Integer, ByVal newString As String)
            Require(Assert.IsInRange(newInt, 0, 100))
            Require(Assert.IsNotNullOrEmpty(newString))
 
            _myInt = newInt
            _myString = newString
 
            Ensure(_myInt = newInt)
            Ensure(_myString = newString)
        End Sub
 
 
    End Class
End Namespace

Writing Invariant checks

Invariant checks ensure that internal state of an object remains valid throughout its lifetime. They are run at every method exit point of the class to guarantee consistency as the code runs.

You should initialise any Invariants in your objects constructor as these should hold true from the moment you instantiate your object.

You can also run the invariant checks at any time by calling the static method Contract.AssertInvariants(this); (or Contract.AssertInvariants(Me) in VB.NET). If you need code to fail before the end of the method, you can also call Contract.Assign() to assign a value and have Invariants Asserted at that time. However a need to do either of these things would often indicate a need to refactor your code in to shorter methods that do less.

The method signature of 'Invariant' is Slightly different to 'Require' and 'Ensure'. Unlike, these methods which run assertions in place, Invariants are not only run at the point of definition, but also on exit from every method on the object. For this reason, the assertion parameter takes a delegate to be called when an invariant is evaluated. The cleanest way to write these is using the 'anonymous' delegate feature of .NET 2.0. In practical terms this simply means a slight change in syntax.


So in the case of ...

Invariant(()=> _myInt > -1 && _myInt < 101, "_myInt should be between 0 and 100");

'myInt > -1 && myInt < 101' is not run in-line, but is a delegate that is called whenever the contract requires it to be evaluated.

C#
using ContractDriven;
 
namespace ContractExample
{
    class ExampleClass : ContractBoundObject
    {
        private int _myInt;
        private string _myString = string.Empty;
 
        public ExampleClass()
        {
            //You can either explicity define logic for an Invariant Assert
            Invariant(()=> _myInt > -1 && _myInt < 101, "_myInt should be between 0 and 100");
            
            //or use one of the built in checks 
            //(these checks can be used by any contract type, "Require", "Ensure", "Invariant")
            Invariant(()=> Assert.IsInRange( _myInt, 0, 100));
            
            //An invariant follows the same pattern as other contracts, but uses a delegate
            //rather than inline execution (as it can be evaluated at any point.)
            Invariant(()=> _myInt != 42, "_myInt must not equal 42");
            Invariant(()=> Assert.IsLengthInRange("_myString", _myString, 0, 20));
        }
 
        public int MyString
        {
            get
            {
                return _myInt;
            }
            set
            {
                //you can assign values as normal...
                _myInt = value;
                //...in this case invariants will be evaluated after the method has returned.    
                //Or, you can assign the value to the property field using the contract.
                //This checks invariants immediatly and is useful in fast fail situations.
                Contract.Assign(this, ref _myInt, value);
            }
        }
 
    }
}

VB.NET
Imports ContractDriven
 
Namespace ContractExample
 
    Class ExampleClass
        Inherits ContractBoundObject
 
        Private _myInt As Integer
        Private _myString As String = String.Empty
 
        Public Sub New()
            'You can either explicity define logic for an Invariant Assert 
            Invariant(Function() _myInt > -1 AndAlso _myInt < 101, "_myInt should be between 0 and 100")
 
            'or use one of the built in checks 
            '(these checks can be used by any contract type, "Require", "Ensure", "Invariant") 
            Invariant(Function() Assert.IsInRange(_myInt, 0, 100))
 
            'An invariant follows the same pattern as other contracts, but uses a delegate 
            'rather than inline execution (as it can be evaluated at any point.) 
            Invariant(Function() _myInt <> 42, "_myInt must not equal 42")
            Invariant(Function() Assert.IsLengthInRange("_myString", _myString, 0, 20))
        End Sub
 
        Public Property MyString() As Integer
            Get
                Return _myInt
            End Get
            Set(ByVal value As Integer)
                'you can assign values as normal... 
                _myInt = value
                '...in this case invariants will be evaluated after the method has returned. 
                'Or, you can assign the value to the property field using the contract. 
                'This checks invariants immediatly and is useful in fast fail situations. 
                Contract.Assign(Me, _myInt, value)
            End Set
        End Property
 
 
    End Class
End Namespace

Checking for Side Effects (Tracking values)

ContractDriven also provides a mechanism to check your code for side-effects as it is run. You do this by comparing values before and after a block of code is run.

To do this, you "track" a value, but calling Contract.Track(value). This returns a key that you keep hold of. After you have run your code, you can then use this key to retrieve the original value and compare this with the new value.

You would normally do this as part of ensuring a post condition, as if your code has failed, you want it to fail with a ContractException.

C#
using ContractDriven;
 
namespace ContractExample
{
 
    class ExampleClass : ContractBoundObject
    {
 
        private int _myInt;
        
        public void IncrementX()
        {
            //track the object
            var key = Track(_myInt);
        
            _myInt += 1;
 
            //ensure that the logic performed correctly
            Ensure(_myInt == (int)Before(key) + 1, "_myInt should equal 1 more than original value");
        }
 
    }
}

VB.NET
Imports ContractDriven
 
Namespace ContractExample
 
    Class ExampleClass
        Inherits ContractBoundObject
        'some private variables 
        Private _myInt As Integer
 
        Public Sub IncrementX()
            'track the object 
            Dim key As Guid = Track(_myInt)
 
            _myInt += 1
 
            'ensure that the logic performed correctly 
            Ensure(_myInt = CInt(Before(key)) + 1, "_myInt should equal 1 more than original value")
        End Sub
 
    End Class
End Namespace

The 'using' pattern

ContractBoundObject implements the IDisposable interface, so you must call Dispose() on your object when you have finished with it. The best practice for doing this is the 'using' keyword, which ensures that Dispose() is called.

C#
//Where ExampleClass decends from ContractBoundObject
using(var t = new ExampleClass())
{
    t.MyInt = 5;
    t.IncrementMyString();
}

VB.NET
'Where ExampleClass decends from ContractBoundObject
Using t As ExampleClass = New ExampleClass()
    t.MyInt = 5
    t.IncrementMyString()
End Using

Overall Design Summary

A quick overview of the design of the library. The design of ContractDriven.NET is fairly straightforward. The major components are:

The Contract Object

The Contract object is at the core of the library. It is a static class which processes assertions. If any of these assertions evaluate as false it will throw a ContractException.

In the case of the Require() and Ensure() methods this is simple. Both of these accept either a boolean condition or an object capable of Evaluating a boolean condition (an Assertion object). In the case of Invariant(), instead of passing in a boolean assertion, a delegate is passed in. This delegate can then be evaluated after each method of the class is run.

Assertion Classes

The Assertion classes (accessed via the static Assert class) provide an easy way to run assertions. Assertion logic is package in a class that provides an Eval() method. When Eval() is called, the assertion logic runs and returns true if the assertion holds and false if not.

The static Assert Class provides a factory through which you can create new Assertion objects.

The Invariant Assertion Cache

The Invariant Cache contains a register of delegates to be executed against an object as required. They are registered by a client object via Contract.Invariant() which can be called in the clients' constructor. A call to Contract.CheckInvariants() evaluates the cached invariants.

The Invarant Assertion Processing Aspect

The invariant "aspect" (a concept taken from Aspect Oriented Programming) . A class which contains Invariants can be marked with the Invariant attribute. This injects a call to Contract.CheckInvariants() after every method call made on the object. This guarantees that invariants remain intact throughout the applications lifetime.

ContractBoundObject base class

The ContractBoundObject provides an implementation of a contract bound object from which a developer can inherit thier classes. The class inherits MarshalByRefObject (required to use invariants) and is marked with the Invarant attribute so that the object takes part in the messaging sink chain described above.

Exception Classes

All Exceptions thrown by ContractDriven.NET are decended from the base type of ContractException, and are one of three types. If Require(Assert.IsNotNull(object)); fails. It will throw a PreconditionException. If however, the precondition is never specified, then the code may throw a NullReferenceException. As the developer you can easily deduce that no contract was ever specified for this case and introduce one if required.

A main principal of CDD is to fail an invalid state before any unexpected exceptions occur. Rather than throw a typed exception related to the assertion in question (for example, throwing a NullReferenceException from an IsNotNull check), by explicity throwing a ContractException means that the calling client is at fault for passing in invalid parameters.

Future Direction and How to Contribute

There are 2 main areas which will be expanded for the next release.

The first part of the plan is to add more Assertion Classes. At the moment, there are a limited number of these to handle common basic checks. These can be expanded upon to cover a whole range of cases. So for example... for strings we could have
  • StringContainsAssertion
  • StringStartsWithAssertion
  • StringAreEqualIgnoringCaseAssertion
  • StringIsMatchAssertion

etc.

This expansion will enable the second major feature of the library which is to provide Extension methods for assertions. Extension methods make the following style of syntax possible...

private void .ctor()
{
   _myPrivateString.Invariant(this).StartsWith("MYPREFIX:");
}

private void DoSomething(int x)
{
   x.Require.IsInRange(0, 10);
}

Currently, the library supports .NET 2.0 and above. However, extension methods are a feature of .NET 3.0, so we need to consider the design and decide whether to separate the extention methods in to an Extentions DLL. If you have any strong opinion please post to the discussion forum.

If you would like to contribute, assertion classes and test cases for these. Please sign up!

Whilst neither required, nor expected, We would love to hear from anyone using the library.

Thank you for your interest and happy coding!

Chris Varley, November 2008.

Last edited May 14, 2009 at 8:39 AM by chris_v, version 6