Chapter 2: Interface Contracts

The Three Laws of Interfaces

  1. An Interface’s Implementation Shall Do What Its Methods Says It Does The name of a method should correspond to the operations that the implementation actually performs. Conversely, an implementation should perform the operations intended by the creator of the interface. The method should return a value or signal an error in accordance with the explained purpose of the method. If the purpose and meaning of a method are not unambiguously obvious from the method’s name and its place within an interface, then those aspects should be clearly documented. 
  2. An Interface Implementation Shall Do No Harm
    Harm refers to an implementation interfering with other modules in a program or with other programs. The user of an interface implementation should expect that the implementation performs its services in an efficient manner.
  3. If An Implementation Is Unable to Perform Its Responsibilities, It Shall Notify Its Caller
    An implementation should always report problems that are encountered and that it cannot fix itself. The manner of report (e.g., the error signal) can either be a return code or be an exception. The errors that are denoted on the interface (either return codes or exceptions) are part of the interface contract; an interface should produce only those errors. An implementation should handle nonspecified situations gracefully.

Design by Contract

Bertrand Meyer popularized Design by Contract in his book Object- Oriented Software Construction (Prentice Hall, 1997). In the book, he discusses standards for contracts between a method and a caller. He introduces three facets to a contract—preconditions, postconditions, and class invariants. The user of an interface needs to ensure that certain conditions are met when calling a method; these stipulations are the preconditions. Each method in an interface specifies certain conditions that will be true after its invocation is complete; those guarantees are the postconditions. The third aspect is the class invariant, which describes the conditions that every object instance must satisfy. When dealing with interfaces, these class invariants are typically properties of a particular implementation, not of the interface methods.

If a precondition is not met, the method may operate improperly. If the preconditions are met and a postcondition is not met, the method has not worked properly. Any implementation of an interface can have weaker preconditions and stronger postconditions. This follows the concept that a derived class can have weaker preconditions and stronger postconditions than the base class.

Contract Checking

An interface implementation is not required to check the preconditions. You may assume that the user has met those preconditions. If the user has not, the implementation is free to fail. Any failures should be reported as in the Third Law of Interfaces.

Testing Interfaces against Contracts

The Design Patterns book states, “Design to an interface, not an implementation.” A parallel guideline exists in testing. “Test to an interface,not an implementation”. This is termed black box testing. Writing tests for an interface can also help you work out difficulties in the interface. You can find ambiguities or unclearness in the contractual obligations, the method definitions, or the protocol. If you find that your interface is hard to test, then it probably will be hard to use. If this happens, you can redesign your interface without even having coded an implementation.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: