# Thursday, May 21, 2009

In my book, I talked a bit about programming by contract and how that makes everyone’s lives easier.  Say I have a method that divides one integer by another

public double Divide(int dividend, int divisor)
{
  return dividend / divisor;
}

I’d like to be able to let callers know that they can’t pass a 0 for the divisor, because that will result in a DivideByZeroException, and nobody wants that.  In the past I had a couple of choices on how to express that, mostly involving writing different kids of code, because C# doesn’t have a native expression of design by contract like Eiffel does.  One way is to use Debug.Assert

public double Divide(int dividend, int divisor)
{
  Debug.Assert(divisor != 0);

  return dividend / divisor;
}

That way any caller that passes a 0 will get an assertion dialog at runtime, which brings it pretty dramatically to everyone’s attention.  The assumption is that using the Debug.Assert will flush out all cases where people are incorrectly calling my method during development, so it’s OK that the assertion will get compiled out of my Release build.  However, that doesn’t make it impossible for a caller to pass a 0 at runtime and cause the exception.  Another option is explicitly checking parameters and throwing a different exception.

public double Divide(int dividend, int divisor)
{
  if (divisor == 0)
      throw new ArgumentException("divisor cannot be zero", "divisor");

  return dividend / divisor;
}

Patrick argues that this has now moved from defining contract to defining behavior, and I can agree with that, although I’d probably argue that it defines both contract and behavior since I’ve extended the functionality of the Debug.Assert to the release build, while also protecting my internal state from bad data.  But that’s really a separate discussion… :)

Now thanks to the Microsoft Code Contracts project, I have a third option.  The Code Contracts project is the evolution of the work done on Spec#, but in a language neutral way.  The Code Contracts tools are currently available from DevLabs for VS 2008, as well as shipping with VS 2010 B 1.  Just at the moment, there are more features in the DevLabs version that what made it into the 2010 beta.  With Code Contracts, I can rewrite my Divide method like this

public double Divide(int dividend, int divisor)
{
  Contract.Requires(divisor != 0);

  return dividend / divisor;
}

I like the syntax, as it calls out quite explicitly that I’m talking about contract, and making an explicit requirement.  The default behavior of this method at runtime is identical to Debug.Assert, it brings up an assertion dialog and brings everything to a screeching halt. However, it’s configurable at build time, so I can have it throw exceptions instead, or do whatever might be appropriate for my environment if the contract is violated.  I can even get the best of both worlds, with a generic version of Requires that specifies an exception

public double Divide(int dividend, int divisor)
{
  Contract.Requires<ArgumentException>(divisor != 0, "divisor");

  return dividend / divisor;
}

I could configure this to bring up the assertion dialog in Debug builds, but throw ArgumentNullException in Release builds.  Good stuff.

The example above demonstrates a required “precondition”.  With Code Contracts, I can also specify “postconditions”. 

public void Transfer(Account from, Account to, decimal amount)
{
  Contract.Requires(from != null);
  Contract.Requires(to != null);
  Contract.Requires(amount > 0);
  Contract.Ensures(from.Balance >= 0);

  if (from.Balance < 0 || from.Balance < amount)
      throw new InsufficientFundsException();

  from.Balance -= amount;
  to.Balance += amount;

}

This isn’t the greatest example, but basically the Transfer method is promising (with the Contract.Ensures method) that it won’t ever leave the Balance a negative number.  Again, this is arguably behavior rather than contract, but you get the point. 

A really nifty feature is that I can write an interface definition and associate it with a set of contract calls, so that anyone who implements the interface will automatically “inherit” the contract validation.  The syntax is a bit weird, but you can see why it would need to be like this…

[ContractClass(typeof(ContractForCalucluator))]
interface ICalculator
{
   int Add(int op1, int op2);
   double Divide(int dividend, int divisor);
}

[ContractClassFor(typeof(ICalculator))]
class ContractForCalucluator : ICalculator
{
   #region ICalculator Members

   public int Add(int op1, int op2)
   {
       return default(int);
   }

   public double Divide(int dividend, int divisor)
   {
       Contract.Requires(divisor != 0);

       return default(double);
   }

   #endregion
}

Now any class that implements ICalculator will have the contract validated for the Divide method.  Cool.  The last thing I want to point out is that the team included a handy sample of how to work with contract validation in your MSTest unit test code.  The Contract class exposes an event called ContractFailed, and I can subscribe to the event to decide what happens on a failure.  For a test assembly, I can do this

[AssemblyInitialize]
public static void AssemblyInitialize(TestContext tc)
{
  Contract.ContractFailed += (sender, e) =>
  {
      e.SetHandled();
      e.SetUnwind();
      Assert.Fail(e.FailureKind.ToString() + " : " + e.Message);
  };
}

which will translate contract failures into test failures with very explicit error messages.  In the case of my Divide method if I run this test

[TestMethod()]
public void DivideContractViolation()
{
  Calculator target = new Calculator(); 
  int dividend = 12; 
  int divisor = 0; 
  double actual;
  actual = target.Divide(dividend, divisor);
  Assert.Fail("Should have failed");
}

I get a test failure of

Test method CalculatorTests.CalculatorTest.DivideContractViolation threw exception:  System.Diagnostics.Contracts.ContractException: Precondition failed: divisor != 0 divisor --->  Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Assert.Fail failed. Precondition : Precondition failed: divisor != 0 divisor.

Cool.  This is definitely something I’ll be looking at more in the future.