Contracts as an Implementation Pattern


The inventor of Design by Contract himself, Bertrand Meyer, notes that the contracts look formal and "shocking to most" who first encounter the concept [Meyer1997]. He adds that they are the foundation of code stability and other quality goals. The authors agree in that contracts are indeed a means to achieve those goals, where it would be hard with unit tests alone.

However, contracts are not as strange to developers as they might appear at first glance. In fact, they are an implementation pattern commonly found in existing code.

Assertions Again

Contracts are a particular form of assertions, as explained earlier. Assertions themselves are not unknown to most developers, and they are frequently used by those more careful in large systems projects. Plain assertions are sometimes considered unnecessary in the presence of unit test suites, but they are hardly a strange and new concept.

Preconditions

In many methods, preconditions are disguised as Guard Clauses.[4] Using preconditions instead makes them easier to locate and enforces sensible rules for methods overwritten by subclasses.

[4] A Guard Clause, as described in [Beck1997], is a condition that is checked at the beginning of a method and that raises some kind of exception when it fails.

Postconditions

Postconditions are often simulated by methods checking a message's result. This is commonly used when the message sent belongs to another module or is supposed to call a different application.

Code like this expresses a healthy mistrust in the developers who wrote the called code. However, it should be the other code's responsibility to enforce the promises made, if only to have it in one place instead of dispersing it throughout the client code. This only works when those promises are documented, which postconditions do better than API documentation.

Class Invariants

Class invariants are not frequently encountered in existing code. However, they are sometimes present without being explicitly formulated. Then, they are an annoying source of what is often called "beginners' faults." An example of this is the equals/hashCode relationship in Java.[5]

[5] The same relationship exists in Smalltalk.

When you overwrite equals() in a class, you have to make sure that equal objects still return the same hash code. However, this is enforced nowhere, and it's stated only in the class library documentation and therefore easily missed by beginners.[6] Of course, veteran developers will always remember it, unless they are in a hurry.

[6] Interestingly, this is considered a class invariant of the class Object by both the Java and Smalltalk documentation. It should instead be an invariant of an interface that specifies hashing (for example, Hashable). However, there is no such interface in Java and of course none in Smalltalk.

Again, having explicitly stated invariants will help locate and enforce them. Developers encountering class invariants (as opposed to those writing them) will probably not find them strange and burdensome but will welcome them as an additional aid.



Extreme Programming Perspectives
Extreme Programming Perspectives
ISBN: 0201770059
EAN: 2147483647
Year: 2005
Pages: 445

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net