Wednesday, February 11, 2009

What is Design by Contract?

This is the first article in a series which I started after I reasoned about "Why is Design by Contract not common practice in Software Enineering?".

Design by Contract is a technique to specify the behavior of a class. It helps to communicate what effects methods will have and what the methods expect before they can be executed. Design by Contract means that the caller of a class and the class itself make a contract, which is described as a set of assertions called Preconditions, Postconditions and Invariants.

So the interface and the implementation of a class is enhanced with additional assertions. Preconditions define obligations for the caller of a method, which have to be satisfied before the method is called. Postconditions will guarantee the outcome of the method. Invariants apply to the class as a whole and define conditions which are valid at the end of each method call.

I show an example in C# for preconditions and postconditions. Preconditions are commonly describes with the term 'require' and postconditions with the term 'ensure'. The property PrinterNames has the postcondition that the delivered list is not null. The method RemovePrinter has three preconditions:

public class Printers
{
    private List<string> names;
    
    public Printers()
    {
        names = new List<string>();
        names.Add("printer1");
        names.Add("printer2");
    }
    
    /// <summary>
    /// List of printer names.
    /// Assertion.Ensure(names != null,"Result is not null");
    /// </summary>
    public List<string> PrinterNames
    {
        get
        {
            Assertion.Ensure(names != null,"Result is not null");
            return names;
        }
    }
    
    /// <summary>
    /// Remove a printer
    /// Assertion.Require(PrinterNames().Count > 0,"There is at least one printer");
    /// Assertion.Require(printerIndex >= 0,"printerIndex is not negative");
    /// Assertion.Require(printerIndex lessThan PrinterNames().Count ,"printerIndex is in range");
    /// </summary>
    public void RemovePrinter(int printerIndex)
    {
        Assertion.Require(PrinterNames.Count > 0,"There is at least one printer");
        Assertion.Require(printerIndex >= 0,"printerIndex is not negative");
        Assertion.Require(printerIndex < PrinterNames.Count ,"printerIndex is in range");
    
        names.RemoveAt(printerIndex);
    }

    ...
}

For further information about Design by Contract please refer to the Eiffel web site or the book Object-Oriented Software Construction

In the next article I will try to answer the question: What are the benefits of Design by Contract?

No comments: