Week and strong contracts in Design by Contact

Answer to Fredrik Normén on Defensive programming and Design by Contract on a routine level.

"Design by Contract is about creating a contract between the client and the supplier. The idea of the Design by Contract theory is to associate a specification with every software elements. This specification will define a contract between client and the supplier. When a supplier writes a contract with the client, it should document the obligations and benefits"

There is always a contract between a software element and its client. The question is if the contract is implicit or explicitly stated. Lets look at an example from the .NET framework:

public virtual void Add(object key, object value)

Member of System.Collections.Hashtable

Summary:
Adds an element with the specified key and value into the System.Collections.Hashtable.

Parameters:
key: The key of the element to add.
value: The value of the element to add. The value can be null.

Exceptions:
System.ArgumentNullException: key is null.
System.ArgumentException: An element with the same key already exists in the System.Collections.Hashtable.
System.NotSupportedException: The System.Collections.Hashtable is read-only.-or- The System.Collections.Hashtable has a fixed size.

A short analysis conducts that the method's contract can be expressed like this:

Precondition:
○ true
Postcondition:
○ If key is null ArgumentNullException is thrown
○ If ContainsKey(key) ArgumentException is thrown
○ Else this[key] == value
○ And Count == old Count + 1
 
An analysis of the contract shows that the contract can be made stronger like this:

Precondition:
○ Key != null
○ !ContainsKey(key)
Postcondition:
○ this[key] == value
○ Count == old Count + 1
 
In the theory of contracts there is this concept of strong versus week contacts where the first is more demanding on the client than the last. Hence, the precondition is now more demanding on the client and this can be taken advantage of in the routine implementation. In the pseudo code below we can see the difference:

Week contract supplier

public virtual void Add(object key, object value) 
{
    if (key == null) 
    {
      throw new ArgumentException(…);
    }
    
    if (ContainsKey(key)) 
    {
      throw new ArgumentException(…);
    }
    
    this.buckets[hashcode(key)] = value;
}

Strong contract supplier

public virtual void Add(object key, object value) 
{
    this.buckets[hashcode(key)] = value;
}

Using the stronger contract we get a much cleaner implementation of the routine. How about the client code then? Well, take a look:

Week contract client

try 
{
    hashtable.Add(key, foo);
} catch (ArgumentException ex) 
{
    // oops, we made a mistake!
}

Strong contract client

if (!hashtable.ContainsKey(key) 
{
    hashtable.Add(key, foo);
}

Of course, the code for the strong contract client can be used with the week contract as well. The main point is that with the strong contract no error handling should be made because then there is an error in the client code which should be corrected, not handled at runtime. The routine only promise to satisfy the post condition if and only if  the pre condition is satisfied by the client. If the pre condition is not met the outcome is undefined and anything can happen from nothing at all to the system crashing. This is where frameworks that permit developers to express the contract in code comes in.

Design-by-Contract Frameworks

As Fredrik mentions Eiffel was the first programming language to have syntactic support for expressively stating contracts. For .NET there has been several attempts to do the same in addition to Spec#. Here is a list:

nContract
MS thesis by Wes Haggard

Example:

[FormallySpecified]
public class Test 
{
    [Pre("i > 0")]
    public void DoWork(int i) { }
}

ContractN
By Dave Sexton

Example:

public class Person : ContractN.ProgrammingByContract
{
    [InRequired, OutRequired]
    public string Name { get; set; }
}

Design by Contract Framework
By Kevin McFarlane

Example:

public virtual int B.Foo(int x)
{
    Check.Require(1 < x < 3);
    ...
    Check.Ensure(result < 15);
    return result;
}

I might find a reason to return with a more thorough review of the frameworks in the future.

Comments (3) -

  • Tenders

    2009-04-15 17:32:18 | Reply

    Thanks for sharing this knowledge Rickard - i will be bookmarking you and referring to the blog regularly for help!

  • Rickard

    2009-04-15 17:49:06 | Reply

    @Tenders: I'm glad to help. What experience do you have with Design By Contract?

Loading
Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.