Specifying Inversion of Control through Contracts for Interfaces

Inversion
of Control
(IoC) is a very important practice to make code testable. It usually
relies on defining interfaces for each external dependency. Various frameworks and
techniques, i.e. Dependency
Injection
(DI), Service
Locator
, exist to bind the interface implementations to the components. In this
blog post, we will *not* focus on this aspects of IoC but rather on it’s main building
block: interfaces. This article describes how Contracts for interfaces
improves IoC… regardless of which DI framework/technique you are using.
The
Contracts for interfaces are a feature of the Code
Contracts for .Net
tool.

Interfaces are not Contracts

Interfaces are often referred to as Contracts in the context of IoC: they
define the methods and properties that a service should implement and are a key factor
in achieving the loose coupling: one can build the code against the interface and
can plug in various implementation with no risks.

Unfortunately, interfaces
are not contracts
: while they specify how the methods signatures should be, interfaces
do not specify the functional behavior
. To illustrate this, let’s take a
look at a well-known simple interface of the BCL:

image

For this interface, I could naively implement as follows:

image

While my implementation is really really wrong, it fulfills all requirements of the
IServiceProvider interface: a method GetService that returns object. Of course, if
I would have read the MSDN documentation of GetService, I would have known that object
should implement serviceType. Unfortunately, the interface did not tell me anything
about that and compilers don’t understand MSDN documentation either.

image 

Contracts for interfaces

Code Contracts provides an
API for design-by-contracts
(pre-condition, post-condition, etc…). It also supports
defining contracts for interface or abstract classes. Contracts for interfaces
can be used to specify the functional behavior of interface members.
While
they also serve as documentation, those contracts can also be turned into runtime
checks or leveraged by static checkers.

image

  • since interface members cannot have method bodies, the contracts are stored in a ‘buddy’
    type.
  • The [ContractClass]/[ContractClassFor]
    attributes bind the interface type and the contract type together.
  • Contract.Result<object>() is
    a helper method to refer to the result value, since this is not supported in C#.

Let’s take a closer look at the body of IServiceProviderContract.GetService. It contains
a pre-condition (Requires) that the serviceType should not be null and a post-condition
(Ensures) that the return value should be null or should be assignable to the serviceType:

image

In this simple case, the contracts captured precisely the specification that we found
in MSDN. The critical difference is that they are stored in a format that compilers
and runtimes know pretty well: MSIL byte code. The benefits are huge:

  • documentation: the contracts are stored in a programming-language agnostic format
    that mined and rendered for your favorite programming language,
  • static checking: static analysis tools can (and will) use contract to try to find
    bugs before you execute the code, or prove that it is correct with respect to the
    contracts,
  • runtime checking: the runtime checker will instrument all implementations
    of the interface with the interface contracts automatically.
    Once
    you’ve specified how an interface should behave, you do not have to repeat yourself
    when re-implementing it, the re-writer takes care of that.
  • automated white box testing: tools like Pex can
    leverage the runtime contract checks to try to find inputs that violate the contracts.
  • IoC/DI framework agnostic: It does not matter which DI framework
    you use, as soon as you use interface, you could also provide contracts for it.