Saturday, December 30, 2006

Contracts in Object Orientated Code

A school of thought, which is widely supported, suggests that when two pieces of code communicate they form a contract. That is if code A ("the client") calls code B ("the supplier") with some data it will expect code B to have certain behaviour, return certain data and handle exceptional/erroneous/odd inputs in a certain way. The idea is called "Design by Contract" (DBC).

It occured to me that DBC could be formalised by extending interfaces into Contracts.

About Design by Contract

In simple terms:

  1. The Supplier expects input data to meet certain conditions - "pre-conditions"
  2. The Client expects the Supplier to behave in certain way - if the Supplier changes or stores data as well as returning output data it is harder to predict what will happen.
  3. The Client expects output data to meet certain conditions - "post-conditions"

Pre-conditions - the Supplier is responsible for checking pre-conditions

Behaviour - if the Supplier code does not alter the state of the system but instead just returns data to the client then the Supplier's code is said to be Side-Effect free - Functional Programming techniques attempt to minimise Side Effects and Imperative Object Orientated techniques attempt to Encapsulate them within a manageable number of lines of code. Behaviour is usually tested by injecting Mock Object's as input data into the Supplier.

Post-Conditions - Client test code is used to create Assertions about the Supplier's code. Test Framework's allow us to create Unit Tests that test different Post-Conditions.

How to extend Object Orientated (OO) Frameworks to support DBC.

Many OO frameworks such as .Net and Java leave it primarily upto the developer to use DBC techniques. As an example in C# a Pre-Condition might be:

if (inputParameter == null)
{
throw new ArgumentNullException("inputParemter");
}

This code simply checks an input parameter to ensure it is not a null reference and throws an exception if it is.

.Net does have an extension called Spec# that adds DBC functionality. Now I don't claim to be an expert on Spec# or any other specific DBC framework, however, it seems to me that DBC would be better implemented by "upgrading" interfaces into Contracts rather than decorating Classes with contract information.

Why extend interfaces to support DBC?

  1. An interface by its nature has public methods, properties etc - it is public and therefore requires a contract
  2. An interface can then have any number of concrete implementations, which all meet the pre and post conditions
  3. An interface can then be a single port of call for all contractual information - function declarations, pre-conditions, post-conditions and exception types
  4. This would negate the need for verbose commenting of functions and reduce the need for a throws keyword in Java
  5. It would reduce the clutter in classes

An Example:

An interface IPerson, which has a single property Name, which cannot be null might look like:

contract CPerson
{
[PreCondition: NotNull(Name)]
string Name
{
get;
set;
}
}

A concrete class would then "agree to"/"support" a contract, including any Pre-conditions and Post-conditions etc.

Any thoughts on this idea are more than welcome!

0 Comments:

Post a Comment

<< Home