<<

by contract What is meant by "" or CS 619 Introduction to OO Design "programming by contract"? and Development contract: An agreement between classes/objects and their clients about how they will be used. Design by Contract ! used to assure that objects always have valid state ! non-software contracts: bank terms, product warning labels

Fall 2013 ! To ensure every object is valid, show that:

! constructors create only valid objects

! all mutators preserve validity of the object

! How to enforce a contract?

Example contract issue Design by Contract!

" A potential problem situation: queue class with " Proposed by for Eiffel remove or dequeue method " Organize communication between software elements – client may try to remove from an empty queue by organizing mutual obligations and benefits " What are some options for how to handle this? " Use a metaphor of – clients: receive services from suppliers ! declare it as an error (an exception) – suppliers: supply services ! tolerate the error (return null)

! print an error message inside the method Client Supplier ! bad because it should leave this up to the caller Obligation Satisfy supplier Guarantee service ! repair the error in some way (retry, etc.) requirement ! bad because it should leave this up to the caller Benefit Get service Impose requirements The decision we make here becomes part of the contract of the queue class! Example: Design by Contract == Dont accept anybody elses garbage!

Client UPS Obligation Provide package of Deliver package to no more than 5kg, recipient in 24 hours each dimension less or less than 2 meters. Pay postage Benefit Get package No need to deal delivered in 24 with deliveries that hours or less are too big, too heavy or unpaid

Client Supplier Obligation Post-condition Benefit Post-condition Precondition

Pre-condition Post-conditions " Whose fault is it when a is not " What happens when a precondition is not met, and what should be done? met? ! postcondition: Something that must be true upon precondition: Something that must be true before object completion of the object's work. promises to do its work. ! Example: At end of sort(int[]), the array is in sorted order. ! Example: A hash map class has a put(key, value) and a get(key) ! Check them with statements at end of methods, if needed. method. ! A postcondition being violated is object's (your) own fault. ! A precondition of the get method is that the key was not modified since the time you put it into the hash map. ! Assert the postcondition, so it crashes if not met.

! If precondition is violated, object may choose any action it likes ! Don't throw an exception -- it's not the client's fault!

! If key was modified, the hash map may state that the key/value is not found, even though it is in the map. ! Document in Javadoc with tag @post.condition! ! Document in Javadoc with tag @pre.condition

Class invariants Support " How is it enforced? " Eiffel : Design as such, but limited usage class : A logical condition that always holds " ++: for any object of a class. – assert() does not throw an exception ! Example: Our account's balance should never be negative. – ! Similar to loop invariants, which are statements that must Documentation extraction difficult be true on every iteration of a loop. " Java ! Can be tested at start or end of every method. – ASSERT is standard since Java 1.4 ! Assert your invariants, so it crashes if they are not met don't throw an exception -- it's not the client's fault! – JavaDoc annotation

! Document class invariants in the Javadoc comment header at the top of the class. (no special javaDoc tag)

Programming Language Support Example:Effiel Example: Stack Specification Stack! Eiffel class stack Effiel Example: Map insert()! Implementors of stack promise • Eiffel is designed as such ... but only used in limited cases invariant: (isEmpty (this)) or that invariant will be true after all (! isEmpty (this)) methods return (incl. constructors) C++ • assert()put (inx: C++ELEMENT assert.h; keydoes: STRING not throw) isan exception public char pop () • It’s possible to mimic assertions (incl. compilation option) in C++ Clients of stack promise -- Insert x so that it will be retrievable through key. require: ! isEmpty (this) + (see “Another Mediocre Assertion Mechanism for C++” ensure: true precondition will be true before require calling pop() by Pedro Guerreiro count in TOOLS2008) <= capacity • Documentation extraction not is key.emptymore difficult but feasible public void push (char) do require: true Implementors of stack promise Java ... Some insertion algorithm ... ensure: (! isEmpty (this)) postcondition will be true after • ASSERT is standard since Java 1.4 Design by Contract in UML ensure Design by and Contract (top (this) =in char) UML push() returns ... however limited “design has by (x )contract” only; acknowledge by Java + see http://java.sun.com/j2se/1.4/docs/guide/lang/assert.html item (key) = x public void top (char) : char Stack • Documentation extraction count using = JavaDocold count annotations + 1 <> <> ... pop Stack(): char Left as an exercise end (! isEmpty (this)) (isEmpt ensure:y (this)) ... or push (char) <> public<>void isEmpty () pop: boolean (): char (! isEmpty (this)) isEmpty(): boolean (! isEmpty (this)) require: ... (isEmpty (this)) or push (char) <> Smalltalk (and other languages) ensure: ... top(): char (! isEmpty (this)) isEmpty(): boolean (! isEmpty (this)) and • Possible to mimic; compilation option requires language idioms top(): char <>(top (this) = char) • Documentation extraction is possible (style Javadoc) 6. Design by Contract (! isEmpty (this)) and 8 (top (this) = char) So what: isn’t this pure documentation? Who will (a) Register these contracts for later reference (the book of laws)? 6. Design by Contract 15 (b) Verify that the parties satisfy their contracts (the police)? SoAnswer what: isn’t this pure documentation? Who will (a) The source code (a)(b) Register The running these contracts system for later reference (the book of laws)? Quiz: What happens when a pre-condition is NOT satisfied ? (b) Verify that the parties satisfy their contracts (the police)? Answer (a) The source code (b) The running system 6. Design by Contract Quiz: What happens when a pre-condition is NOT satisfied ? 9 Assertions Assertions in Source Code • assertion = any boolean expression we expect to be true at some point. 6. Design by Contract 9 public char pop() throws AssertionException { my_assert(!this.isEmpty()); Assertions.. return _store[_size--]; • Help in writing correct software my_assert(invariant()); ➡ formalizing invariants, and pre- and post-conditions my_assert(true); //empty postcondition • Aid in maintenance of documentation } ➡ specifying contracts IN THE SOURCE CODE ➡ tools to extract interfaces and contracts from source code • Serve as test coverage criterion private boolean invariant() { ➡ Generate test cases that falsify assertions at run-time return (_size >= 0) && (_size <= _capacity);} • Should be configured at compile-time ➡ to avoid performance penalties with trusted parties ➡ What happens if the contract is not satisfied? private void my_assert(boolean assertion) throws AssertionException { if (!assertion) { Should be turned on/off via Quiz: What happens when a pre-condition is NOT satisfied ? throw new AssertionException compilation option • = What should an object do if an assertion does not hold? ("Assertion failed");} ➡ Throw an exception. }

6. Design by Contract 11

6. Design by Contract 12 Assertion Violations Assertions in Java

The assertions can be monitored dynamically at run-time " Java assert statements to debug the software – assert ;

– A precondition violation would indicate a bug at the – assert : ; caller " will raise an AssertionError if " – A postcondition violation would indicate a bug at the is false. callee " enabling assertions

– when compiling: javac -source 1.5 Our goal is to prevent assertion violations from happening ClassName.java – The pre and postconditions are not supposed to fail if – when running: java -ea ClassName the software is correct ( so they differ from exceptions and ) " In C/C++, assert is a compile-time thing. In Java, can selectively en/disable assertions at runtime.

Debug and ship builds Checking Pre-conditions! Most companies have at least two versions of their code: " debug build : has special code only for the developer Assert pre-conditions to inform clients when they – debug print statements or graphical output violate the contract. " – assertions for pre/postconditions, invariants " public Object top() {! " !assert(!this.isEmpty()); !// pre-condition! " ship build : meant to be used by customers " !return top.item;! – Users expect reasonable performance and reliability. }! – The app should not spend a lot of time checking for " pre/post or invariants (in ship build). ! " The same code is used to make debug and ship build. Always check pre-conditions, raising exceptions if they – special flags (e.g. DEBUG_MODE) turn on and off debug code fail.! – in Java, VM can be run with flags to turn on/off debug also Checking Post-conditions! Checking Class Invariants! Assert post-conditions and invariants to inform yourself when you violate the contract." Every class has its own invariant:! " " !public void push(Object item) {! protected boolean invariant() {! ! !top = new Cell(item, top);! !return (size >= 0) &&! ! !size++;! ! !( (size == 0 && this.top == null)! ! !assert !this.isEmpty(); ! !!!// post-condition! ! !|| (size > 0 && this.top != null));! ! !assert this.top() == item; ! !// post-condition! ! !assert invariant();! ! ! !! }! !}!

" Check them whenever the implementation is non-trivial."

Example Running Javadoc with tags

Consider int array binary search code: " javadoc -source 1.5 - output_folder_name /** Returns index of value n in array a. -tag pre.condition:cm:"Precondition:" * @pre.condition The array a is in sorted order. -tag post.condition:cm:"Postcondition:" file_name.java */ public static void binarySearch(int[] a, int n) { assert isSorted(a) : "Array must be sorted"; ... " Javadoc output will } show pre, postconditions

private static boolean isSorted(int[] a) { for (int i = 0; i < a.length - 1; i++) if (a[i] > a[i+1]) return false; return true; } Inheritance: Pre-conditions Inheritance: Post-conditions

" If the precondition of the " If the postcondition of the Client ClassA Client ClassA ClassB.someMethod is ClassB.someMethod is stronger than the someMethod() weaker than the someMethod() precondition of the postcondition of the ClassA.someMethod, then ClassA.someMethod, then this is not fair to the Client this is not fair to the Client ClassB ClassB

" The code for ClassB may someMethod() " Since Client may not have someMethod() have been written after known about ClassB, it Client was written, so could have relied on the Client has no way of stronger guarantees knowing its contractual provided by the requirements for ClassB ClassA.someMethod

Inheritance In ClassA: In ClassB which is derived from ClassA: invariant invariant classInvariant newClassInvariant " Liskov Substitution Principle someMethod() is someMethod() is require require – Wherever an instance of a class is expected, an Precondition newPrecondition instance of one of its subclasses can be substituted. do do Procedure body Procedure body " Therefore, ensure ensure – A subclass may keep or weaken the preconditions of Postcondition newPostcondition end end an overridden method Client ClassA – A subclass may keep or strengthen the postconditions The precondition of ClassB.aMethod is defined as: of an overridden method someMethod() newPrecondition or Precondition

– A subclass may keep or strengthen the invariants of a The postcondition of ClassB.aMethod is defined as: subclass ClassB newPostcondition and Postcondition

someMethod() The invariant of ClassB is classInvariant and newClassInvariant