April 2011

Volume 26 Number 04

Cutting Edge - Give Your Classes a Software Contract

By Dino Esposito | April 2011

image: Dino EspositoAn old but good practice of software development recommends that you place at the top of each method—before any significant behavior takes place—a barrier of conditional statements. Each conditional statement checks a different condition that input values must verify. If the condition isn’t verified, the code throws an exception. This pattern is often referred to as If-Then-Throw.

But is If-Then-Throw all that we need to write effective and correct code? Is it sufficient in all cases?

The notion that it may not be sufficient in all cases isn’t a new one. Design by Contract (DbC) is a methodology introduced several years ago by Bertrand Meyer based on the idea that each piece of software has a contract in which it formally describes what it expects and what it provides. The If-Then-Throw pattern nearly covers the first part of the contract; it lacks entirely the second part. DbC isn’t natively supported in any mainstream programming language. However, frameworks exist to let you taste flavors of DbC in commonly used languages such as Java, Perl, Ruby, JavaScript and, of course, the Microsoft .NET Framework languages. In .NET, you do DbC via the Code Contracts library added to the .NET Framework 4, located in the mscorlib assembly. Note that the library is available to Silverlight 4 applications but not to Windows Phone applications.

I believe that nearly every developer would agree in principle that a contract-first approach to development is a great thing. But I don’t think so many are actively using Code Contracts in .NET 4 applications, now that Microsoft has made software contracts available and integrated in Visual Studio. This article focuses on the benefits of a contract-first approach for code maintainability and ease of development. You can hopefully use arguments in this article to sell Code Contracts to your boss for your next project. In future installments of this column, I’ll drill down into aspects such as configuration, runtime tools and programming features such as inheritance.

Reasoning About a Simple Calculator Class

Code Contracts are a state of mind; you shouldn’t put them aside until you’re called to design a big application that requires a super architecture and employment of many cutting-edge technologies. Keep in mind that—when poorly managed—even the most powerful technology can cause problems. Code Contracts are useful for just about any type of application, as long as you have a good grasp of them. So let’s start with a simple class—a classic Calculator class such as this:

public class Calculator
{
    public Int32 Sum(Int32 x, Int32 y)
    {
        return x + y;
    }

    public Int32 Divide(Int32 x, Int32 y)
    {
        return x / y;
    }
}

You’ll probably agree that the code here isn’t realistic, as it lacks at least one important piece: a check to see if you’re attempting to divide by zero. As we write a better version of it, let’s also assume that we have an additional issue to deal with: The calculator doesn’t support negative values. Figure 1 has an updated version of the code that adds a few If-Then-Throw statements.

Figure 1 The Calculator Class Implementing the If-Then-Throw Pattern

public class Calculator
{
    public Int32 Sum(Int32 x, Int32 y)
    {
        // Check input values
        if (x <0 || y <0)
            throw new ArgumentException();


        // Perform the operation
        return x + y;
    }

    public Int32 Divide(Int32 x, Int32 y)
    {
        // Check input values
        if (x < 0 || y < 0)
            throw new ArgumentException();
        if (y == 0)
            throw new ArgumentException();

        // Perform the operation  
        return x / y;
    }
}

So far, we can state that our class either starts processing its input data or, in the case of invalid input, it just throws before doing anything. What about the results generated by the class? What facts do we know about them? Looking at the specifications, we should expect that both methods return a value not less than zero. How can we enforce that and fail if it doesn’t happen? We need a third version of the code, as shown in Figure 2.

Figure 2 The Calculator Class Checking Preconditions and Postconditions

public class Calculator
{
    public Int32 Sum(Int32 x, Int32 y)
    {
        // Check input values
        if (x <0 || y <0)
            throw new ArgumentException();

        // Perform the operation
        Int32 result = x + y;

        // Check output
        if (result <0)
            throw new ArgumentException();

        return result;
    }

    public Int32 Divide(Int32 x, Int32 y)
    {
        // Check input values
        if (x < 0 || y < 0)
            throw new ArgumentException();
        if (y == 0)
            throw new ArgumentException();

        // Perform the operation
        Int32 result = x / y;

        // Check output
        if (result < 0)
            throw new ArgumentException();

        return result;
    }
}

Both methods now are articulated in three distinct phases: check of the input values, performance of the operation and check of the output. Checks on input and output serve two different purposes. Input checks flag bugs in your caller’s code. Output checks look for bugs in your own code. Do you really need checks on the output? I admit that check conditions can be verified via assertions in some unit tests. In that case, you don’t strictly need such checks buried in the runtime code. However, having checks in the code makes the class self-describing and makes it clear what it can and can’t do—much like the terms of a contracted service.

If you compare the source code of Figure 2 with the simple class we started with, you’ll see that the source grew by quite a few lines—and this is a simple class with few requirements to meet. Let’s take it one step further.

In Figure 2, the three steps we identified (check input, operation and check output) run sequentially. What if the performance of the operation is complex enough to accommodate additional exit points? What if some of these exit points refer to error situations where other results are expected? Things can really get complicated. To illustrate the point, however, it suffices that we add a shortcut exit to one of the methods, as shown in Figure 3.

Figure 3 A Shortcut Exit Duplicates the Code for Postconditions

public Int32 Sum(Int32 x, Int32 y)
{
    // Check input values
    if (x <0 || y <0)
        throw new ArgumentException();
            
    // Shortcut exit
    if (x == y)
    {
        // Perform the operation
        var temp = x <<1; // Optimization for 2*x

        // Check output
        if (temp <0)
            throw new ArgumentException();

        return temp;
    }

    // Perform the operation
    var result = x + y;

    // Check output
    if (result <0)
        throw new ArgumentException();

    return result;
}

In the sample code (and it is just an example), method Sum attempts a shortcut if the two values are equal—multiplying instead of summing. The code used to check output values, however, must be replicated for each early exit path in the code.

The bottom line is that nobody can reasonably think of taking a contract-first approach to software development without some serious tooling, or at least a specific helper framework. Checking preliminary conditions is relatively easy and cheap to do; dealing manually with post-execution conditions makes the entire code base unwieldy and error prone. Not to mention a few other ancillary aspects of contracts that would make the source code of classes a real mess for developers, such as checking conditions when input parameters are collections and ensuring that the class is always in a known valid state whenever a method or a property is called.

Enter Code Contracts

In the .NET Framework 4, Code Contracts is a framework that provides a much more convenient syntax to express a class contract. In particular, Code Contracts support three types of contracts: preconditions, postconditions and invariants. Preconditions indicate the preliminary conditions that should be verified for a method to execute safely. Postconditions express the conditions that should be verified once the method has executed either correctly or because of a thrown exception. Finally, an invariant describes a condition that’s always true during the lifetime of any class instance. More precisely, an invariant indicates a condition that must hold after every possible interaction between the class and a client—that is, after executing public members, including constructors. The conditions expressed as invariants aren’t checked and subsequently may be temporarily violated after the invocation of a private member.

The Code Contracts API consists of a list of static methods defined on the class Contract. You use the Requires method to express preconditions and Ensures to express postconditions. Figure 4 shows how to rewrite the Calculator class using Code Contracts.

Figure 4 The Calculator Class Written Using Code Contracts

using System.Diagnostics.Contracts;
public class Calculator
{
    public Int32 Sum(Int32 x, Int32 y)
    {
        Contract.Requires<ArgumentOutOfRangeException>(x >= 0 && y >= 0);
        Contract.Ensures(Contract.Result<Int32>() >= 0);

        if (x == y)
            return 2 * x;

        return x + y;
    }

    public Int32 Divide(Int32 x, Int32 y)
    {
        Contract.Requires<ArgumentOutOfRangeException>(x >= 0 && y >= 0);
        Contract.Requires<ArgumentOutOfRangeException>(y > 0);

        Contract.Ensures(Contract.Result<Int32>() >= 0);

        return x / y;
    }
}

A quick comparison of Figure 3 and Figure 4 shows the power of an effective API for implementing DbC. Method code is back to a highly readable form in which you distinguish only two levels: contract information including both preconditions and postconditions and actual behavior. You don’t have to mix conditions with behavior, as in Figure 3. As a result, readability is greatly improved, and maintaining this code gets much easier for the team. For example, you can quickly and safely add a new precondition or edit postconditions at will—you intervene in just one place and your changes can be clearly tracked.

Contract information is expressed via plain C# or Visual Basic code. Contract instructions aren’t like classic declarative attributes, but they still maintain a strong declarative flavor. Using plain code instead of attributes increases the programming power of developers, as it makes it more natural to express the conditions you have in mind. At the same time, using Code Contracts gives you more guidance when you refactor the code. Code Contracts, in fact, indicate the behavior you should expect from the method. They help maintain coding discipline when you write methods and help keep your code readable even when preconditions and postconditions get numerous. Even though you can express contracts using a high-level syntax such as that in Figure 4, when code actually gets compiled, the resulting flow can’t be much different from the code outlined in Figure 3. Where’s the trick, then?

An additional tool integrated in the build process of Visual Studio—the Code Contracts rewriter—does the trick of reshaping the code, understanding the intended purpose of expressed preconditions and postconditions and expanding them into proper code blocks placed where they logically belong. As a developer, you just don’t worry about where to place a postcondition and where to duplicate it if, at some point, you edit the code to add another exit point.

Expressing Conditions

You can figure out the exact syntax of preconditions and postconditions from the Code Contracts documentation; an up-to-date PDF can be obtained from the DevLabs site at bit.ly/f4LxHi. I’ll briefly summarize it. You use the following method to indicate a required condition and otherwise throw the specified exception:

Contract.Requires<TException> (Boolean condition)

The method has a few overloads you might want to consider. The method Ensures expresses a postcondition:

Contract.Ensures(Boolean condition)

When it comes to writing a precondition, the expression will usually contain only input parameters and perhaps some other method or property in the same class. If this is the case, you’re required to decorate this method with the Pure attribute to note that executing the method won’t alter the state of the object. Note that Code Contract tools assume property getters are pure.

When you write a postcondition, you may need to gain access to other information, such as the value being returned or the initial value of a local variable. You do this through ad hoc methods such as Contract.Result<T> to get the value (of type T) being returned from the method, and Contract.OldValue<T> to get the value stored in the specified local variable at the beginning of the method execution. Finally, you also have a chance to verify a condition when an exception is thrown during the execution of the method. In this case, you use the method Contract.EnsuresOnThrow<TException>.

Abbreviators

The contract syntax is certainly more compact than using plain code, but it can grow large as well. When this happens, readability is at risk again. A natural remedy is grouping several contract instructions in a subroutine, as shown in Figure 5.

Figure 5 Using ContractAbbreviators

public class Calculator
{
    public Int32 Sum(Int32 x, Int32 y)
    {
        // Check input values
        ValidateOperands(x, y);
        ValidateResult();

        // Perform the operation
        if (x == y)
            return x<<1; 
        return x + y;
    }

    public Int32 Divide(Int32 x, Int32 y)
    {
        // Check input values   
        ValidateOperandsForDivision(x, y);
        ValidateResult();

        // Perform the operation
        return x / y;
    }

    [ContractAbbreviator]

    private void ValidateOperands(Int32 x, Int32 y)
    {
        Contract.Requires<ArgumentOutOfRangeException>(x >= 0 && y >= 0);
    }

    [ContractAbbreviator]
    private void ValidateOperandsForDivision(Int32 x, Int32 y)
    {
        Contract.Requires<ArgumentOutOfRangeException>(x >= 0 && y >= 0);
        Contract.Requires<ArgumentOutOfRangeException>(y > 0);
    }

    [ContractAbbreviator]

    private void ValidateResult()
    {
        Contract.Ensures(Contract.Result<Int32>() >= 0);
    }
}

The ContractAbbreviator attribute instructs the rewriter on how to correctly interpret the decorated methods. Without the attribute to qualify it as a sort of macro to expand, in fact, the ValidateResult method (and other ValidateXxx methods in Figure 5) would contain rather inextricable code. What would, for example, Contract.Result<T> refer to, as it’s used in a void method? Currently, the ContractAbbreviator attribute must be explicitly defined by the developer in the project, as it isn’t included in the mscorlib assembly. The class is fairly simple:

namespace System.Diagnostics.Contracts
{
    [AttributeUsage(AttributeTargets.Method, 
      AllowMultiple = false)]
    [Conditional("CONTRACTS_FULL")]
    internal sealed class 
      ContractAbbreviatorAttribute : 
      System.Attribute
    {
    }
}

Clean, Improved Code

Summing up, the Code Contracts API—basically the Contract class—is a native part of the .NET Framework 4, as it belongs to the mscorlib assembly. Visual Studio 2010 comes with a configuration page in the project properties specific to the configuration of Code Contracts. For each project, you must go there and explicitly enable runtime checking of contracts. You also need to download runtime tools from the DevLabs Web site. Once on the site, you pick up the proper installer for the version of Visual Studio you have. Runtime tools include the Code Contracts rewriter and interface generator, plus the static checker.

Code Contracts help you write clean code by forcing you to indicate expected behavior and results for each method. At the very minimum, this gives guidance when you go to refactor and improve your code. There’s a lot more to be discussed about Code Contracts. In particular, in this article, I just quickly mentioned invariants and didn’t mention the powerful feature contract inheritance at all. In future articles, I plan to cover all of this and more. Stay tuned!


Dino Esposito is the author of “Programming Microsoft ASP.NET MVC”(Microsoft Press, 2010) and coauthor of “Microsoft .NET: Architecting Applicationsfor the Enterprise” (Microsoft Press, 2008). Based in Italy, Esposito is a frequent speaker at industry events worldwide. Follow him on Twitter at twitter.com/despos.

Thanks to the following technical expert for reviewing this article: Brian Grunkemeyer