BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News .NET 4 Feature Focus: Code Contracts

.NET 4 Feature Focus: Code Contracts

This item in japanese

Bookmarks

Last year we started talking about Spec#, a language based on C# that supports design by contract. Design by contract builds on top of concepts like static typing, where certain actions cannot be performed unless it can be verified at compile time. Contracts usually take the form of pre- and post-conditions such as a parameter or return value never being null or only containing a certain range of values.

Rather than force developers to learn a whole new language such as Spec#, Microsoft is working on a language-agnostic library that can be leveraged by any .NET language. In some ways contracts look like assertions, but they are very different under the covers. Contracts are supported by a combination of static code analysis, which can be both inside and outside the compiler, as well as by testing frameworks. They are also executable, meaning they behave like assertions when running a debug build. Consider this first example:

string GetDescription(int x){
Contract.Requires(x>0);
Contract.Ensures(Contract.Result<string>() != null);

Looking at just the signature, developers only get the static type information "GetDescription requires an integer and returns a string". With the contracts, both developers and tools know "GetDescription requires a positive integer and returns a string that is never null".

In addition to explicit contracts, the contract checker can also support implicit contracts. One such example is division by zero. If a class includes a division of integers where the divisor is a variable, then all code paths must ensure that the variable is never zero or a warning is issued. If the variable in question is a property on a unsealed class, this would require checking in every subclass as well. There are also implicit contracts for dereferencing nulls and array indexes.

To make this easier, there is the concept of an ObjectInvariant method. This special method, which only contains contracts, is injected into the end of each method call to ensure the object's state remains consistent. It is important to note that this applies to all methods, including those in subclasses from other assemblies.

Another time saving device is easy access to old values. In this example the Ensures contract is used in conjunction with the OldValue syntax to make certain that the collection's count property is incremented.

Public Sub Add(value as Object) 
Contract.Ensure(Count = Contract.OldValue(Count) + 1) 

Even though the contract is written at the top of the method, it will automatically be moved to just before the Return statement by the compiler. As there is some overhead for storing the old value of Count, this sort of check will only occur in debug builds.

In order to support library developers, release builds include a reference assembly. For example, the Widgets.dll assembly would have the bulk of its contracts extracted and placed in the assembly Widgets.Contracts.dll. This allows client developers to use the faster release-style builds while still leveraging the contracts created by the library developers.

One of the more interesting features is that contracts do not just apply to concrete functions. Even interface and abstract methods with no other implementation detail can have contracts. This is done by creating a reference implementation of the interface whose sole purpose is to hold contracts. This reference implementation is linked back to the interface by attributes.

There are no restrictions on the contents of a contract. Since the same contracts are used for both static and runtime checking, a complex constraint that cannot be evaluated by one may still be checked by the other. Contracts can also be extracted by documentation generators.

For more information on Contracts in .NET 4, check out the first half of this PDC keynote.

Rate this Article

Adoption
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Community comments

  • contracts and business logic

    by Fernando Felman,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    I think this technology is a great stability and maintenance boost but it comes with huge risk: the potential to make wonderful spaghetti out of the business rules.

    When dealing with pure algorithms this technology is great – it will ensure the input you get matches the meaning you had in mind when creating the function. This will mostly be the case for libraries and frameworks which deals with generic concerns such as data structure (arrays, trees) or high level concepts (mathematical or graphical library).

    The problem for such a technology is that it makes it too easy to put the business logic all the system. Think of a simple scenario: a Customer object that have an ID, a name and some orders. Using this technology you can easily contract the ID for a particular format, the name to be not empty and the orders to be non-negative. You’d also want to maintain those constraints throughout the systems so if you’ve a function dealing with ID you’d probably decorate its inputs with the same contracts. But then business rules changed causing the contracts to change which might have a known down effect on a big systems as you’ll have to modify the contracts throughout the whole system.

    True, it is possible to prevent such problem i.e. treat business rules in a different way than the more abstract rules (e.g. business rules in an engine rules and abstract constraints using code contracts) but this distinction is not trivial and I’m quite concerned that some developers might overuse the power given by this technology.

    In essence, before incorporating this in my projects I’d like to see some supporting tools to make sure it’s not being misused (FxCop or something similar can do the trick).

  • Delphi Prism (ex Oxygene) already support this; no need to wait for .NET 4

    by El Cy,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Bellow I included some interesting links regarding Delphi Prism

    Delphi Prism Language
    prismwiki.codegear.com/wiki/Language

    Delphi Prism vs. C#
    prismwiki.codegear.com/wiki/Delphi_Prism_vs._CS...


    Delphi Prism
    www.codegear.com/products/delphi/prism

    Delphi Prism - new language features for Delphi .NET developers
    blogs.codegear.com/andreanolanusse/2008/10/29/d...

    Interview with marc hoffman: "Delphi Prism - Visual Studio Pascal For .NET"
    www.bitwisemag.com/2/Delphi-Prism-Visual-Studio...

  • Re: contracts and business logic

    by Jonathan Allen,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    But then business rules changed causing the contracts to change which might have a known down effect on a big systems as you’ll have to modify the contracts throughout the whole system.


    You are probably going to have to propagate those business rules throughout your code base anyways. The fact that they have contracts associated with them may just end up making it easier to find all the places that need to be changed.

  • Re: contracts and business logic

    by Fernando Felman,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    But then business rules changed causing the contracts to change which might have a known down effect on a big systems as you’ll have to modify the contracts throughout the whole system.


    You are probably going to have to propagate those business rules throughout your code base anyways. The fact that they have contracts associated with them may just end up making it easier to find all the places that need to be changed.


    Very true and that's why I think code contract has the potential to create mess, but I wouldn't say not using them will prevent the mess. Basically, code contracts gives developers from all layers (data, business logic, presentation, proxies, etc.) the power to declare rules in the source-code. Though a powerful capability by itself, I'm concern it’s too easy to misuse it especially since it’s a new technology with no governance usage or best practices.
    I'll try to put it in a different way. If you have no code contracts you're more likely to plan in advance how business rules are to be used throughout all layers; and so you're less likely to give developers from all layers the ability to declare business rules in the code. This in turn has the potential to enable less painful changes to the business rules as you can anticipate where to find those rules.

  • Re: contracts and business logic

    by Jeff Santini,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    But then business rules changed causing the contracts to change which might have a known down effect on a big systems as you’ll have to modify the contracts throughout the whole system.


    You are probably going to have to propagate those business rules throughout your code base anyways. The fact that they have contracts associated with them may just end up making it easier to find all the places that need to be changed.


    Why are you going to propogate your business rules everywhere? Wrap them in a type and pass it everywhere, then your business rules live in only one place. Eric Evans specification that he discusses in Domain Driven Design is a good example. Maybe I have just been lucky but it has been many years since I have seen the need to spray business rules throughout my code base.

  • Re: contracts and business logic

    by Fredrik Klintebäck,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    ...Though a powerful capability by itself, I'm concern it’s too easy to misuse it especially since it’s a new technology with no governance usage or best practices.
    ...

    The technology isn't new, it has been around at least two decades. Most notably, in the programming language Eiffel, invented by Bertrand Meyer in 1985 I think.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

BT