<<

Foundations of by Contract

Fall 2020 Department of Computer Science Ben-Gurion university

Based on slides of: Mira Balaban Department of Computer Science Ben-Gurion university R. Mitchell and J. McKim: by Example Who’s to blame?

The components fit but the system does not work. Who’s to blame? The component developer or the system integrator?

“Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live”

2 Design by Contract Topics in Software Engineering, Fall 2019 Design by Contract  The Design by Contract (DBC) software development technique ensures high quality software by guaranteeing that every component of a system lives up to its expectations.

 As a developer using DBC, you specify component contracts as part of the component's interface.

 The contract specifies what that component expects of clients and what clients can expect of it.

3 Design by Contract Topics in Software Engineering, Fall 2019 Design By Contract  The term Design by Contract was coined by while designing the Eiffel within Eiffel Software company.  Eiffel implements the Design by Contract principles.  Bertrand Meyer won the 2006 ACM Software System Award for Eiffel

The Eiffel Tower, built in 1887 for the 1889 World Fair, was completed on time and within budget, as will software projects written in Eiffel.

4 Design by Contract Topics in Software Engineering, Fall 2019 Design By Contract  DbC is an approach for designing computer software.  It prescribes that software should define precise verifiable interface specifications for software components based upon the theory of abstract data types and the conceptual metaphor of business contracts  DbC is a metaphor on how elements of a software system collaborate with each other, on the basis of mutual obligations and benefits.  The metaphor comes from business life:  a client and a supplier agree on a contract.  the contract defines obligations and benefits.

5 Design by Contract Topics in Software Engineering, Fall 2019 A contract  There are two parties  A Client - requests a service  A Supplier - supplies the service

 A Contract is the agreement between the client and the supplier  Two major characteristics of a contract  Each party expects some benefits from the contract and is prepared to incur some obligations to obtain them  These benefits and obligations are documented in a contract document

 Benefit of the client is the obligation of the supplier, and vice versa.

6 Design by Contract Topics in Software Engineering, Fall 2019 DbC – The idea and metaphor  Motivation: Organize communication between software elements  By organizing mutual obligations and benefits  Do it by a metaphor of  clients – request services from suppliers  suppliers – supply services

Client Supplier Obligation Satisfy supplier Guarantee service requirement Benefit Get service Impose requirements

7 Design by Contract Topics in Software Engineering, Fall 2019 DbC – The metaphor realization  Obligations and benefits are specified using contracts  Write contracts for classes and methods  Methods:   Post-conditions  Classes: Invariants

Client Supplier Obligation Post-condition Benefit Post-condition Precondition

8 Design by Contract Topics in Software Engineering, Fall 2019 What happens when a Contract Breaks?  If everyone does their job, there is no problem  If the precondition is not satisfied –  the Customer is wrong! (The client has a bug).  If the precondition is satisfied, but the is not  the Service is wrong (The service has a bug).

 From the Client’s perspective, “true” is the best precondition. In general, weaker preconditions are better.  From the Server’s perspective, “false” is the best precondition. In general, stronger preconditions mean an easier job with the implementation.

9 Design by Contract Topics in Software Engineering, Fall 2019 DbC Nature  DbC promotes software specification together with or prior to code writing  Writing contracts needs some principles and guidelines  The DbC principles tell us how to organize a class features (attributes, methods)  The contract of a class is its interface

10 Design by Contract Topics in Software Engineering, Fall 2019 Design by Contract, by Example

11 Design by Contract Topics in Software Engineering, Fall 2019 Notations features

attributes routines

functions procedures

creation other COMMANDS

12 Design by Contract Topics in Software Engineering, Fall 2019 Six Principles – the SIMPLE_STACK example

Topics in Software Engineering, Fall Design by Contract 13 2019 SIMPLE_STACK example – initial try  SIMPLE_STACK is a generic class, with type parameter G: Simple_stack of G.  Features: G  Queries – functions; No side effect: SIMPLE_STACK  count(): Integer  is_empty(): Boolean count()  Initialization: is_empty() initialize()  initialize() push(g:G)  Commands: pop()  push(g:G)no return value.  pop(): out parameter g:G; no return value.

14 Design by Contract Topics in Software Engineering, Fall 2019 Example (1)  Writing a contract for push:  Takes a parameter g.  Places g on the top of the stack. push(g:G) Purpose: Push g onto the top of the stack. ensure: g = pop ???

15 Design by Contract Topics in Software Engineering, Fall 2019 Example (2)  Writing a contract for push:  Takes a parameter g.  Places g on the top of the stack. push(g:G) Purpose: Push g onto the top of the stack. ensure: g = pop ??? but pop does not return a value. Just removes. Redesign pop: pop(): G purpose: Remove top item and return it.

New push contract: push(g:G) Purpose: Push g onto the top of the stack. ensure: g = pop 16 Design by Contract Topics in Software Engineering, Fall 2019 A. Separate commands from queries (1)  Serious problem:  Evaluation of the post-condition changes the stack!  Solution: Split pop into two operations: 1. Query: top(): G purpose: return the item at the top of the stack. 2. Command: delete() purpose: deletes the item at the top of the stack.  push contract: push(g:G) purpose: Push g onto the top of the stack. ensure: top = g

17 Design by Contract Topics in Software Engineering, Fall 2019 A. Separate commands from queries (2)  Standardize names:  Class: SIMPLE_STACK  Queries:  count(): Integer  purpose: No of items on the stack.  item(): G  purpose: The top item  is_empty(): Boolean Boolean queries have  purpose: Is the stack empty? names that invite a yes/no  Creation commands: question  initialize()  purpose: Initialize a stack (new or old) to be empty.  Operations (other commands):  put(g:G)  purpose: Push g on top of the stack. A standard name to add  remove() /delete item from any  purpose: Removes the top item of the stack. container class

18 Design by Contract Topics in Software Engineering, Fall 2019 A. Separate commands from queries  Principle 1: Separate commands from queries.

 Queries: Return a result. No side effects. Pure functions.  Commands: Might have side effects. No return value.

 Some operations are a mixture:  pop() – removes the top item and returns it →Separate into two pore primitive command and query of which it is mixed

19 Design by Contract Topics in Software Engineering, Fall 2019 B. Separate basic queries from derived queries (1) is_empty(): Boolean  Post-condition of is_empty: purpose: Is the stack empty? ensure: consistent_with_count: Result = (count()=0)  Result is a contract built-in variable that holds the result that a function returns to its caller.  The effect of is_empty() is defined in terms of the count query. → is_empty() is a derived query: It can be replaced by the test: count() = 0. → Contracts of other features can be defined in terms of basic queries alone. No need to state the status of derived queries – no need to state in the post-condition of put() that is_empty() is false.

state: count is increased infer : is_empty=false from the contract of is_empty

20 Design by Contract Topics in Software Engineering, Fall 2019 Separate basic queries from derived queries (2)  Principle 2: Separate basic queries from derived queries.  Derived queries can be specified in terms of basic queries.

 Principle 3: For each derived query, write a post-condition that defines the query in terms of basic queries.

21 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (1)  Queries provide the interface of an object:  all information about an object is obtained by querying it.  Derived queries are defined in terms of basic queries (principle3). → The effect of a command on an object should be specified in terms of basic queries.

For Simple_stack, define the effects of put() initialize() remove() in terms of the basic queries count() item() 22 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (2)  The put command:  put() increases count by 1.  put() affects the top item. put(g:G) Purpose: Push g onto the top of the stack. ensure: count_increased: count() = count()@pre + 1 g_on_top: item() = g  “@pre” is borrowed from OCL (Object Constraint Language)  count()@pre refers to the value of the query count() when put() is called.

23 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (3)  The initialize() command:  Turns count() to 0: → post-condition count() = 0. initialize() purpose: Turns a stack (new or old) to be empty. ensure: stack_is_empty: count() = 0  Following initialization the stack includes no items. Therefore, no top item → The query item() cannot be applied.  Implies a pre-condition for the query item: item() : G purpose: The top item on the stack. require: stack_is_not_empty: count() > 0  Together, the 2 contracts, guarantee that applying item after initialize is illegal!

24 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (4)  The remove() command:  Two effects:  Reduces the number of items by one.  Removes the top item, and uncovers the item pushed before the top one.  Pre-condition: Stack is not empty. remove() purpose: The top item on the stack. require: stack_not_empty: count() > 0 ensure: count_decreased: count() = count()@pre - 1  Problem: How to express the 2nd post-condition? The only queries are count and item. No way to refer to previous items.

25 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (5)  Rethink the basic queries.  Needed: A basic query that enables querying any item on the stack.  New basic query: item_at(i : Integer) : G purpose: The i-th item on the stack. item_at(1) is the oldest; item_at(count) is the youngest, and the stack top. require: i_large_enough: i > 0 i_small_enough: i <= count  The new basic queries are:  count()  item_at() → The contracts of all other queries and commands need to be redefined!

26 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (6)  The item query is no longer a basic query  It turns into a derived query: item = item_at(count)

item() : G purpose: The top of the stack. require: stack_not_empty: count() > 0 ensure: consistent_with_item_at: Result = item_at(count())

27 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (7)  The put command revisited:

put(g : G) purpose: Push g on top of the stack. ensure: count_increased: count() = count()@pre + 1 g_on_top: item()item_at(count() = g ) = g

28 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (8)  The initialize creation command revisited: initialize() purpose: Initialize the stack to be empty. ensure: empty_stack: count() = 0 item_at is undefined: --For item_at(i), i must be in the interval [1,count], which is empty, since count = 0 -- there are no values of i for which item_at(i)_ is defined

 The precondition of item_at(i)* together with count()=0 implies the second post-condition – this is summarized as a comment

* i_large_enough: i > 0, i_small_enough: i <= count

29 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (9)  The remove command revisited:

remove() purpose: Remove the top item from the stack. The new top is the one, put before the last one. require: stack_not_empty: count() > 0 ensure: count_decreased: count() = count()@pre - 1

 No need for another post-condition about the new top:  Once count is decreased, the new top of the stack: item() - is item_at(count() )

30 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (10)  Principle 4: For each command, specify its effect on basic queries.  Implies its effect on derived queries.  Usually: Avoid specifying queries that do not change.

 Principle 5: .  Constrains clients. For each query and command, determine a pre-condition

31 Design by Contract Topics in Software Engineering, Fall 2019 summary  Every command specifies its effect on every basic query  Sometimes the specification is direct – an explicit assertion in the post condition  Sometimes the specification is indirect  Initialize specifies that count =0. The precondition of item_at() implies that there are no valid values of i for which item_at can be called  Indirectly initialize specifies the effect on item_at: it makes it invalid to call item_at()  All the derived queries have post conditions that specify their results in terms of the basic queries

32 Design by Contract Topics in Software Engineering, Fall 2019 Class invariants and class correctness  A class is an assertion that holds for all instances (objects) of the class  A must be satisfied after creation of every instance of the class  The invariant must be preserved by every method of the class, i.e., if we assume that the invariant holds at the method entry it should hold at the method exit  We can think of the class invariant as conjunction added to the precondition and post-condition of each method in the class

33 Design by Contract Topics in Software Engineering, Fall 2019 Class invariants  Capture unchanging properties of a class objects by invariants  For the SIMPLE_STACK class, the non-negative value of count is an invariant:

invariant: count_is_never_negative:  Argument (proof): count() >= 0  For an initialized object: count() = 0  Count() is decreased by remove, but it has the precondition:  count() > 0

 Principle 6: Write invariants to define unchanging properties of objects.  Provide a proof for each invariant.  A good collection of class invariants might involve all method contracts (in their proofs)  (if the invariant can be inferred from the contracts of the features it is redundant.  Include it ?

34 Design by Contract Topics in Software Engineering, Fall 2019 The SIMPLE_STACK class interface (1)  Class SIMPLE_STACK(G) count(): Integer 1. Basic queries: purpose: The number of items on the stack

item_at(i : Integer) : G purpose: The i-th item on the stack. item_at(1) is the oldest; item_at(count) is the youngest, and the stack top. require: i_large_enough: i > 0 i_small_enough: i <= count() item() : G 2. Derived queries: purpose: The top of the stack. require: stack_not_empty: count() > 0 ensure: consistent_with_item_at: Result = item_at( count () )

is_empty: Boolean purpose: Is the stack empty from items? 35 Design by Contract Topics in Software Engineering, Fall 2019 The SIMPLE_STACK class interface (2)  Class SIMPLE_STACK(G) … 3. Creation commands:

initialize() purpose: Initialize the stack to be empty. ensure: empty_stack: count() = 0 item_at is undefined: For item_at(i), i must be in the interval [1,count], which is empty, since count = 0

36 Design by Contract Topics in Software Engineering, Fall 2019 The SIMPLE_STACK class interface (3) 4. Other commands:

put(g : G) purpose: Push g on top of the stack. ensure: count_increased: count() = count()@pre + 1 g_on_top: item_at(count() ) = g

remove purpose: Remove the top item from the stack. The new top is the one, put before the last one. require: stack_not_empty: count() > 0 ensure: count_decreased: count() = count()@pre – 1

5. Invariant: count_is-never_negative: count() >= 0

37 Design by Contract Topics in Software Engineering, Fall 2019 The basic queries form a conceptual model  The two basic queries count and item_at give us a model of a stack object  Using this model we can say all there is to say about stacks:  What the stuck looks like when it is just been initialized: Count = 0 and there are no items since there is no i for which items_at(i) is valid.  What the effect of put(g) is : count is increased a g is item_at(count)  What the effect of remove is: count has decreased  What the result of is_empty is: The same as count=0  What the result of item is: the same as item_at(count)

38 Design by Contract Topics in Software Engineering, Fall 2019 The basic queries form a conceptual model  We have devised a conceptual model of stacks.  Stacks have an ordered set of items  (item_at(1), item_at(2),item_at(3), and so on)  We know how many items there are  Count 30 Count=3 item_at(3)=30 20 item_at(2)=20 10 item_at(1)=10

 The class devises the model and uses it as the basis of the contracts that specify the features of the class.  The programmer of the class can see the model and devise a suitable implementation model to represent it.

39 Design by Contract Topics in Software Engineering, Fall 2019 The 6 principles 1. Separate commands from queries. 2. Separate basic queries from derived queries. 3. For each derived query, write a post-condition that defines the query in terms of basic queries. 4. For each command, specify its effect on basic queries. 5. For each query and command, determine a pre-condition. 6. Write invariants to define unchanging properties of objects.

40 Design by Contract Topics in Software Engineering, Fall 2019 Design by Contract and Inheritance

Topics in Software 41 Design by Contract Engineering, Fall 2019 Design by Contract and inheritance  Subclasses inherit features of their super-classes  Subclasses also inherit the contracts of their inherited features  Subclasses can redefine features of their super-classes.  Subclasses can redefine the contracts of their inherited features, BUT: They must respect the inherited contracts Class COURIER Features: … deliver( p: Package, t: Time, : Destination ) : Time Purpose: Deliver package p accepted at time t to destination d. result is the delivery time. require: package_small_enough: p.weight() < 5 ensure: fast_delivery: Result < t + 3 …

42 Design by Contract Topics in Software Engineering, Fall 2019 Redefining a pre-condition (1)  Consider a subclass of COURIER that redefines the pre-condition on the deliver feature: class SPECIAL_COURIER extends COURIER redefine deliver and a COURIER client holding an object of SPECIAL_COURIER  If the new pre-condition is: feature

deliver( p: Package, t: Time, d: Destination ) : Time require: package_small_enough: p.weight() < 8

then the client will have no problem: A client of COURIER knows the pre-condition of COURIER on deliver: package_small_enough: p.weight() < 5 Therefore, if it respects the COURIER pre-condition, its concrete SPECIAL_COURIER object will perform the delivery.

43 Design by Contract Topics in Software Engineering, Fall 2019 Redefining a pre-condition (2)

 If the new pre-condition is: feature deliver( p: Package, t: Time, d: Destination ) : Time require: package_small_enough: p.weight() < 3 a COURIER client that actually holds a SPECIAL_COURIER object might have a problem: A client of COURIER knows the pre-condition of COURIER on deliver: package_small_enough: p.weight() < 5 But respecting the COURIER pre-condition might still invalidate the pre-condition of the concrete SPECIAL_COURIER object on the deliver, and the delivery would be rejected.

Conclusion: A subclass can only weaken a pre-condition: Pre-condition of super implies pre-condition of sub-class

44 Design by Contract Topics in Software Engineering, Fall 2019 Redefining a post-condition (1)

 If the new post-condition is: feature deliver( p: Package, t: Time, d: Destination ) : Time ensure: fast_delivery: Result < t + 2

then the client will have no problem: A client of COURIER knows the post-condition of COURIER on deliver: fast_delivery: Result < t + 3 Therefore, its concrete SPECIAL_COURIER object satisfies its expected benefit.

45 Design by Contract Topics in Software Engineering, Fall 2019 Redefining a post-condition (2)  If the new post-condition is: feature deliver( p: Package, t: Time, d: Destination ) : Time ensure: fast_delivery: Result < t + 5 then a COURIER client that actually holds a SPECIAL_COURIER object might have a problem: A client of COURIER knows the post-condition of COURIER on deliver: fast_delivery: Result < t + 3 But its concrete SPECIAL_COURIER object might not satisfy its expected benefit from the delivery service.

Conclusion: A subclass can only strengthen a post-condition: Post-condition of sub-class implies post-condition of super- class

46 Design by Contract Topics in Software Engineering, Fall 2019 Redefining a contract pre-condition  Redefined pre-conditions are combined with their super-class assertions.  A redefined pre-condition is or-ed with its super pre-condition: package_small_enough: p.weight() < 5 reduces to package_small_enough: p.weight() < 8 or package_small_enough: p.weight() < 8

which indeed is within the obligation of the delivery service of the sub- class while

package_small_enough: p.weight() < 5 reduces to package_small_enough: p.weight() < 5 or package_small_enough: p.weight() < 3

which might not be within the obligation of the delivery service of the sub-class!  DbC languages do not enable strengthening a pre-condition 47 Design by Contract Topics in Software Engineering, Fall 2019 Redefining a contract post-condition  Redefined post-conditions are combined with their super-class assertions.  A redefined post-condition is and-ed with its super post-condition:

fast_delivery: Result < t + 3 reduces to and fast_delivery: Result < t + 2 fast_delivery: Result < t + 2

which indeed, is provided by the delivery service of the sub-class while

fast_delivery: Result < t + 3 reduces to and fast_delivery: Result < t + 5 fast_delivery: Result < t + 3

which might not be provided by the delivery service of the sub-class!

 DbC languages do not enable weakening a post-condition 48 Design by Contract Topics in Software Engineering, Fall 2019 Redefining a contract

 Redefined assertions are marked explicitly:

class SPECIAL_COURIER extends COURIER redefine deliver feature deliver( p: Package, t: Time, d: Destination ) : Time Purpose: Deliver package p accepted at time t to destination d. result is the delivery time. Require of super class require else: or else require this package_small_enough: p.weight() < 8 ensure of super class ensure then: and then ensure this fast_delivery: Result < t + 2

49 Design by Contract Topics in Software Engineering, Fall 2019 Invariants and inheritance  Invariants of a super-class are respected by its sub-classes  Objects of a sub-class must satisfy the inherited invariants class COURIER … invariant insurance > 1,000,000

class SPECIAL_COURIER extends COURIER … invariant Good: insurance > 2,000,000 Bad: insurance > 800,000 Invariants of super-classes are anded with the invariants of the sub-classes A sub-class can only strengthen an invariant

50 Design by Contract Topics in Software Engineering, Fall 2019 Guarded post-conditions in super-classes  If post-conditions in a super-class are guarded (conditioned) by some pre- conditions, then sub-classes can relax (weaken) post-conditions class feature put( g: G ) Purpose: Add g require g_not_in_aggregate: not has( g ) ensure g_added: has( g ) number_of_items_increases: count() = count()@pre + 1

class RELAXED_C extends C feature put( g: G ) Purpose: Add g; if g exists, do nothing require else g_in_aggregate: has( g ) ensure then g_added: has( g ) PROBLEM number_of_items_increases: count() = count()@pre 51 Topics in Software Engineering, Fall 2019 Design by Contract Guarded post-conditions in super-classes  A version with guarded post-conditions: class C put( g: G ) require g_not_in_aggregate: not has( g ) ensure g_added: ( ( not has(g) )@pre ) implies has( g ) number_of_items_increases: ( ( not has(g) )@pre ) implies count() = count()@pre + 1  Now the relaxed subclass can be properly defined: class RELAXED_C extends C put( g: G ) require else g_in_aggregate: has( g ) ensure then g_added: has( g ) OK number_of_items_unchanged: ( has(g)@pre ) implies count() = count()@pre

52 Design by Contract Topics in Software Engineering, Fall 2019 Guidelines  To support redefinition of features, guard each postcondition clause with its corresponding precondition.  This allows unexpected redefinitions by those developing subclasses.

53 Design by Contract Topics in Software Engineering, Fall 2019 Design by Contract – pros and cons

Topics in Software 80 Design by Contract Engineering, Fall 2019 Benefits of Design by Contract  Better  More systematic designs  Modularity  No need to read whole class files  Read contracts  Implementations may change  Contract guarantees certain relevant behaviour  Helps ensure inheritance is properly handled  Improve reliability  Better understood and hence more reliable code  Better tested and hence more reliable code  Assertions are checked at runtime thereby testing that routines fulfill their stated contracts.

81 Design by Contract Topics in Software Engineering, Fall 2019 Benefits of Design by Contract  Better documentation  Contracts form part of the public or client view of a class  Assertions are checked at runtime thereby testing that the stated contracts are consistent with the actual routines  Help  When an assertion fails its location is precisely known.  When assertions are switched on in production, customer may provide the support developer with information regarding a failure.  Support reuse  Good documentation for library users  Avoid

82 Design by Contract Topics in Software Engineering, Fall 2019 Meyer’s Perspective on Defensive Programming  Defensive programming:  leads to duplicate checks on preconditions and therefore code bloat.  leads to implementers checking preconditions when they have no idea what to do if the precondition is false.  leads to confusion over responsibility for ensuring certain constraints.  Meyer’s advice is, “Don’t do it!”  Think about this in the context of preconditions and .

83 Design by Contract Topics in Software Engineering, Fall 2019 Efficiency and Defensive programming  Avoid inefficient defensive checks.  For example, the sqrt method assumes that its argument is non- negative.  When this method is called from trusted code ( e.g. , their input is trusted) this trust is validated by checking the preconditions during debugging, but these checks can be turned off for production use of the program.  Defensive checks are sometimes not possible to execute efficiently.  For example, a binary search method requires that its array argument be sorted.  Checking that an array is sorted requires time linear in the length of the array, but the binary search routine is supposed to execute a logarithmic time.  Therefore the defensive checks would slow down the method unacceptably.  contracts, are easier to automatically remove when the program goes into production,→ much more efficient.

84 Design by Contract Topics in Software Engineering, Fall 2019 Design by Contract Cons  Cost of writing contracts  New language  Takes practice - writing good contracts is a skill.  False sense of security – contract improve programs – they don’t make them perfect.  Quality – not always the primary goal (e.g, early release)  Not all specifications can be described with existing facilities of DbC.  Example: DbC doesn’t support specifications that define performance issues such as execution time and required resources – performance contracts.

 Checking contract violation may be more time consuming than the method execution.  Example: Class that works on Hamiltonian cycle graphs. Its preconditions need to solve NP-Complete problem.

85 Design by Contract Topics in Software Engineering, Fall 2019 Runtime checking

 In a programming environment that understands contracts, we would be told something like the following (we’ll assume the CUSTOMER_MANAGER component has been implemented by a class ofStopped the same in object name): [0xE96978] Class: CUSTOMER_MANAGER Feature: add Problem: Precondition violated Tag: id_not_already_active Arguments: a_customer: BASIC_CUSTOMER_DETAILS [0xE9697C] Call stack: CUSTOMER_MANAGER add was called by CUSTOMER_MANAGER_UIF change_customer

86 Design by Contract Topics in Software Engineering, Fall 2019 Runtime checking Working through this wealth of debugging information line by line, we can tell 1. That the application has stopped in some object (we could open the object with an object browser and examine its attributes). 2. That this object is of the class CUSTOMER_MANAGER. 3. That a problem arose when that class’s add feature was called. 4. That the problem was that some part of the precondition on add was violated. 5. That if a precondition is violated, it means some client called the add feature when it was not legal to do so. Specifically, it was the part of the precondition with the id_not_already_active tag that was violated. 6. Which BASIC_CUSTOMER_DETAILS object was passed as an argument to the call. 7. The sequence of calls that led up to the problem: A change_customer feature in a CUSTOMER_MANAGER_UIF class (the user interface to the customer manager application) called the add feature in the CUSTOMER_MANAGER class.

87 Design by Contract Topics in Software Engineering, Fall 2019 JML –  http://www.cs.iastate.edu/~leavens/JML/  An implementation of DBC for Java  One of many  combines the design by contract approach of Eiffel  JMLEclipse is a JML front-end implemented as an Eclipse plugin.  Open source

88 Design by Contract Topics in Software Engineering, Fall 2019 JASS – Java with ASSertions  Pre-compiler tool written in Java.  Translates annotated contracts into dynamic checking code.  Violation of specification is indicated by Java exception.  Free of charge.  Website: http://csd.informatik.uni-oldenburg.de/~jass/

89 Design by Contract Topics in Software Engineering, Fall 2019 jContractor – implementation of Design By Contract  Contracts in jContractor are written as Java methods that follow a simple naming convention.  All contracts are written in standard Java  no need to learn a special contract specification language.  Assertions are written as Java methods that return a boolean value  jContractor provides runtime contract checking by instrumenting the bytecode of classes that define contracts.  jContractor can  either add contract checking code to class files to be executed later,  or it can instrument classes at runtime as they are loaded.  Contracts can be written in the class that they apply to, or in a separate contract class.

90 Design by Contract Topics in Software Engineering, Fall 2019 91 Design by Contract Topics in Software Engineering, Fall 2019