Design By Contract comes to .Net
‘Design By Contract’ (DBC) is something the Pragmatic Programmers are very keen on. Introduced as part of the Eiffel language some years ago, it’s a way of specifying how your classes and methods are used in more detail than you get by simple type-checking.
For example, say you had a method that divided some numbers:
The fact that your inputs are Integers means they can only contain certain values, but in this case if ‘Divisor’ contained zero, you’d have a DivideByZeroException on your hands. A contract would enable you to specify that ‘Devisor’ must be positive, or could not be zero. A more common example might be to ensure that an object passed as a parameter was not null.
You can also specify requirements on the return values from methods, or on objects as a whole – ‘whenever this object is in existence, the Foo parameter will not be null’, that kind of thing. By doing this, you’re specifying a contract with users of your code: ‘If you ensure my method is called with the correct parameter values, I’ll guarantee that the return value will be within the specified range’.
This has never been much of a concern to most .Net developers, because although there are some libraries available that implement a kind of DBC for .Net, they are somewhat limited because they’re not part of the language, and certainly not widely used. Generally, people wanting to implement a simple form of this type of checking would do so with exceptions or assertions:
But that’s all about to change! As of .Net 4.0, currently in Beta 2, DBC will be officially part of .Net, under the name Code Contracts. In fact Code Contracts is available now for VS2008 / .Net 3.5 if you want to get started with it straight away. Originally called Spec#, this has been a Microsoft Research project for a while but previously only worked with C#. Now it’s been fully productionized and added into mscorlib, with additional tools for compilation and static checking, and it’s all integrated into Visual Studio.
So now if we wanted to do the above check, we’d need to add a reference to Microsoft.Contracts (if we’re using vs2008), put a using in for System.Diagnostics.Contracts, and add the following code:
‘Wow’, I hear you mutter sarcastically, ’you’ve replaced an Exception with some slightly different code..’. But there’s more to it than that – for a start, as well as checking parameters, you can specify what a method’s output will be using a contract, and you can also specify that an object of a class will always be in a certain state:
As well as the Contract.Requires() which specifies the valid parameter states, you can see Contract.Ensures() which defines the valid return value of a method, and the method marked with [ContractInvariantMethod] which states that an object of the class must always be in that state. The checks here are pretty basic – you could, for example, check that all of the data items in the return list were valid – but hopefully you get the idea.
So what happens when one of these checks fails? By default, you get an assertion failure, but you can also get a ContractException, or even define your own custom behaviour. You also have the choice of whether the checks should be performed only during development or for the release build. As you can see from the Project Properties screen in Visual Studio, there are a fair few options:
You might have noticed in the screenshot some options for static checking. The static checker is a clever tool which actually analyses your code during compilation and gives you warnings if it can see something that doesn’t meet the specified contracts. For example, if I tried to call my DataGenerator with an invalid parameter of zero:
I would get the following warnings that a contract check was going to fail, including the location of the problem and the contract check:
Good stuff! Although from what I understand, this only works well if you’re very thorough and put contract checks on everything, as validating the code statically like this is a very difficult computing problem.
A few other interesting things that Code Contracts does, which you mainly can’t do with exception-style checking:
- Contracts for interfaces
- Contracts inherited from base classes
- Code Snippets for common situations (e.g. Requires(!String.IsNullOrEmpty())
Aside from the obvious fact that you will find problems with your code more immediately, as Andy Hunt and Dave Thomas point out in The Pragmatic Programmer, the big advantage with doing DBC of any kind is that it makes you think about the valid state of your inputs, outputs and classes. This probably goes as far in improving your code quality as the contract checking itself.
But whether you like the idea or not, as of around March 2010, Code Contracts will officially be a part of .Net, so if I were you I’d start looking into it!