96
Software Engineering Design by Contract Software Engineering 2012 - 2013 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: Design by Contract by Example

Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Software Engineering

Design by Contract

Software Engineering 2012 - 2013 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: Design by Contract by Example

Page 2: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Design By Contract The term Design by Contract was coined by Bertrand

Meyer while designing the Eiffel programming language within Eiffel Software company.

Eiffel implements the Design by Contract principles.

Bertrand Meyer won the 2006 ACM Software System Award for Eiffel

Software Engineering, 2012 Design by Contract 2

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.

Page 3: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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.

Software Engineering, 2012 Design by Contract 3

Page 4: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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

requirement

Guarantee service

Benefit Get service Impose requirements

Software Engineering, 2012 Design by Contract 4

Page 5: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

DbC – The metaphor realization

Obligations and benefits are specified using contracts

Write contracts for classes and methods

Methods:

Preconditions

Post-conditions

Classes: Invariants

Client Supplier

Obligation Precondition Post-condition

Benefit Post-condition Precondition

Software Engineering, 2012 Design by Contract 5

Page 6: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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 postcondition 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.

Software Engineering, 2012 Design by Contract 6

Page 7: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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

Software Engineering, 2012 Design by Contract 7

Page 8: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Design by Contract, by Example

Software Engineering, 2012 Design by Contract 8

Page 9: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

COMMANDS

Notations features

attributes routines

procedures

creation other

functions

Software Engineering, 2012 Design by Contract 9

Page 10: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Six Principles –

the SIMPLE_STACK example

Software Engineering, 2012 Design by Contract 10

Page 11: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

SIMPLE_STACK example – initial try

SIMPLE_STACK is a generic class, with type parameter G:

Simple_stack of G.

Features:

Queries – functions; No side effect:

count(): Integer

is_empty(): Boolean

Initialization:

initialize()

Commands:

push(g:G) no return value.

pop(): out parameter g:G; no return value.

SIMPLE_STACK

count()

is_empty()

initialize()

push(g:G)

pop()

G

Software Engineering, 2012 Design by Contract 11

Page 12: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Separate commands from queries (1)

Writing a contract for push: Takes a parameter g.

Places g on the top of the stack.

but pop does not return a value. Just removes. Redesign pop:

New push contract:

push(g:G)

Purpose: Push g onto the top of the stack.

ensure:

g = pop ???

pop(): G

purpose: Remove top item and return it.

push(g:G)

Purpose: Push g onto the top of the stack.

ensure:

g = pop

Software Engineering, 2012 Design by Contract 12

Page 13: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Separate commands from queries (2) Serious problem:

Evaluation of the post-condition changes the stack!

Solution: Split pop into two operations: 1. Query:

2. Command:

push contract:

top(): G

purpose: return the item at the top of the stack.

delete()

purpose: deletes the item at the top of the stack.

push(g:G)

purpose: Push g onto the top of the stack.

ensure:

top = g

Software Engineering, 2012 Design by Contract 13

Page 14: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Separate commands from queries (3) Standardize names:

Class: SIMPLE_STACK Queries:

count(): Integer

purpose: No of items on the stack.

item(): G

purpose: The top item

is_empty(): Boolean

purpose: Is the stack empty?

Creation commands: 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.

remove()

purpose: Removes the top item of the stack.

A standard name to add

/delete item from any

container class

Boolean queries have names

that invite a yes/no question

Software Engineering, 2012 Design by Contract 14

Page 15: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Separate commands from queries (4)

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

Software Engineering, 2012 Design by Contract 15

Page 16: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Separate basic queries from derived

queries (1) Post-condition of is_empty:

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

is_empty(): Boolean

purpose: Is the stack empty?

ensure:

consistent_with_count:

Result = (count()=0)

Software Engineering, 2012 Design by Contract 16

Page 17: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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.

Software Engineering, 2012 Design by Contract 17

Page 18: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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()

Software Engineering, 2012 Design by Contract 18

Page 19: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Specify how commands affect basic

queries (2) The put command:

put() increases count by 1. put() affects the top item.

“@pre” is borrowed from OCL (Object Constraint Language)

count()@pre refers to the value of the query count() when put() is called.

put(g:G) Purpose: Push g onto the top of the stack.

ensure:

count_increased:

count() = count()@pre + 1

g_on_top:

item() = g

Software Engineering, 2012 Design by Contract 19

Page 20: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Specify how commands affect basic

queries (3) The initialize() command:

Turns count() to 0: post-condition 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:

Together, the 2 contracts, guarantee that applying item after initialize is illegal!

initialize()

purpose: Turns a stack (new or old) to be empty. ensure:

stack_is_empty:

count() = 0

item() : G

purpose: The top item on the stack.

require:

stack_is_not_empty:

count() > 0

Software Engineering, 2012 Design by Contract 20

Page 21: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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.

Problem: How to express the 2nd post-condition?

The only queries are count and item. No way to refer to previous items.

remove() purpose: The top item on the stack.

require: stack_not_empty: count() > 0 ensure: count_decreased:

count() = count()@pre - 1

Software Engineering, 2012 Design by Contract 21

Page 22: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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:

The new basic queries are:

count()

item_at()

The contracts of all other queries and commands need to be redefined!

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

Software Engineering, 2012 Design by Contract 22

Page 23: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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)

Software Engineering, 2012 Design by Contract 23

Page 24: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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_at(count() ) = g

Software Engineering, 2012 Design by Contract 24

Page 25: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Specify how commands affect basic

queries (8) The initialize creation command revisited:

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

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

Software Engineering, 2012 Design by Contract 25

Page 26: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Specify how commands affect basic

queries (9) The remove command revisited:

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() )

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

Software Engineering, 2012 Design by Contract 26

Page 27: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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:

For each query and command, determine a pre-condition.

Constrains clients.

Software Engineering, 2012 Design by Contract 27

Page 28: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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

Software Engineering, 2012 Design by Contract 28

Page 29: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Class invariants and class correctness

A class invariant is an assertion that holds for all instances

(objects) of the class

A class invariant 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

Software Engineering, 2012 Design by Contract 29

Page 30: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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:

Argument (proof):

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 ?

invariant:

count_is_never_negative:

count() >= 0

Software Engineering, 2012 Design by Contract 30

Page 31: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

The SIMPLE_STACK class interface (1)

Class SIMPLE_STACK(G)

1. Basic queries:

2. Derived queries:

count(): Integer 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 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?

Software Engineering, 2012 Design by Contract 31

Page 32: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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

Software Engineering, 2012 Design by Contract 32

Page 33: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

The SIMPLE_STACK class interface (3)

4. Other commands:

5. Invariant:

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

count_is-never_negative: count() >= 0

Software Engineering, 2012 Design by Contract 33

Page 34: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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)

Software Engineering, 2012 Design by Contract 34

Page 35: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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

The class designer 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.

30

20

10

Count=3

item_at(3)=30

item_at(2)=20

item_at(1)=10

Software Engineering, 2012 Design by Contract 35

Page 36: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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.

Software Engineering, 2012 Design by Contract 36

Page 37: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Building Support for Contracts -

Immutable (Value) Lists

Software Engineering, 2012 Design by Contract 37

Page 38: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts for Immutable (Value) Lists

Contracts are written in expression languages, without side effects (functional languages). (Why? -- recall the Simple_stack class)

Contracts for clients of collection classes need to inspect the members of their collections.

Such contracts need side-effect protected operations on collections.

A conventional approach: Contracts that handle collection objects create them as value (immutable objects). A client can hold a regular collection object, like a hash table, but create an

immutable copy for the purpose of contract evaluation.

We start by defining the code for Immutable list

Software Engineering, 2012 Design by Contract 38

Page 39: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

The IMMUTABLE_LIST class interface (1)

IMMUTABLE_LIST is a generic class, with type parameter G: IMMUTABLE_LIST of G.

Features: Basic Queries:

Derived queries:

Head (): G

Purpose: The first item on the list

Tail (): IMMUTABLE_LIST(G)

Purpose: A new list, formed from the current list (termed ‘self’, minus the ‘head’

is_empty (): Boolean Purpose: Does the list contain no items?

count (): INTEGER

Purpose: The number of items in the list

Software Engineering, 2012 Design by Contract 39

Page 40: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

The IMMUTABLE_LIST class interface (2)

Features: derived Queries:

Creation commend:

cons(g:G): IMMUTABLE_LIST(G)

Purpose: A new list, formed from g as a head and the self list as a tail

is_equal( other: IMMUTABLE_LIST(G) ) : BOOLEAN

Purpose: Compare all ordered elements in self and in other

item( i:INTEGER ): G Purpose: The i-th item in the list (starting from 1)

sublist( from_position:INTEGER, to_position:INTEGER ) : IMMUTABLE_LIST(G)

Purpose: A new list, formed from the self items at from_position to to_position

initialize ()

Purpose: Initialize a list to be empty

Software Engineering, 2012 Design by Contract 40

Page 41: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts of the basic queries

Basic Queries:

No post conditions: regular for basic queries

head (): G

Purpose: The first item on the list

require:

not_empty: not is_empty()

tail (): IMMUTABLE_LIST(G)

Purpose: A new list, formed from the self list, minus the ‘head’

require:

not_empty: not is_empty()

is_empty: Boolean

Purpose: Does the list contain no items?

Software Engineering, 2012 Design by Contract 41

Page 42: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contract of the creation command

The creation command initialize empties a list (either new or old).

It takes no arguments – no precondition

Following its application: 1. The list should be empty. 2. head() and tail() should not be applicable 3. is_empty() should be true

Arguments for the post conditions on head() and tail():

Their pre-condition require: not is_empty(), which is false following initialize()

Creation command: initialize ()

Purpose: Initialize a list to be empty

ensure:

empty: is_empty()

Software Engineering, 2012 Design by Contract 42

Page 43: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts of the derived queries: count

The post-condition of count():INTEGER 1. If the list is empty, count() is 0. 2. If the list is not empty, count() is the count() on the tail of the

list + 1. Derived query:

count ():INTEGER Purpose: The number of items in the list

ensure:

count_zero_for_an_empty_list:

is_empty() implies (Result = 0)

count_for_a_non_empty_list:

not is_empty() implies (Result = tail().count() + 1) Evaluated recursively

Software Engineering, 2012 Design by Contract 43

Page 44: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts of the derived queries: cons

The post-condition of cons(g:G ):IMMUTABLE_LIST):

1. The new list has, g as its head.

2. The new list has self as its tail.

3. The new list is not empty

Derived query:

cons ( g:G ):IMMUTABLE_LIST)

Purpose: A new list, formed from self and g, as its head

ensure:

not_empty: not Result.is_empty()

head_is_g: Result.head() = g

tail_is_self: Result.tail ().is_equal(self)

Software Engineering, 2012 Design by Contract 44

Page 45: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts of the derived queries: item

1. The pre-condition of item(i:INTEGER):G is that i is in the range [1..count()]

2. The post-condition of item(i:INTEGER):G: 1. The 1st item is the head

2. For i>=1, the i-th item is the (i-1)-th item of the tail

Derived query:

The if operator evaluates its else component only if its predicate evaluates to false (or else – eiffel)

item ( i:INTEGER ):G

Purpose: The i-th item on the list

require:

i_large_enough: i >= 1

i_small_enough: i <= count()

ensure:

correct_item: if i=1

then Result = head()

else Result = tail().item(i-1)

( i=1 and Result = head()

orelse

Result = tail().item(i-1)

Evaluated recursively

Software Engineering, 2012 Design by Contract 45

Page 46: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts of the derived queries: item

1. The pre-condition of item(i:INTEGER):G is that i is in the range [1..count()]

2. The post-condition of item(i:INTEGER):G: 1. The 1st item is the head

2. For i>=1, the i-th item is the (i-1)-th item of the tail

Derived query:

The if operator evaluates its else component only if its predicate evaluates to false (or else – eiffel)

item ( i:INTEGER ):G

Purpose: The i-th item on the list

require:

i_large_enough: i >= 1

i_small_enough: i <= count()

ensure:

correct_item: if i=1

then Result = head()

else Result = tail().item(i-1)

( i=1 and Result = head()

orelse

Result = tail().item(i-1)

Evaluated recursively

Evaluation of postcondition for the list [5,4,7,2] with i=3

[5,4,7,2].item(3)=

[4,7,2].item(2)= --i.e. item(i-1) of tail

[7,2].item(1)= --again item(i-1) of tail

7 --this time i=1 so the result is the head of the list

Software Engineering, 2012 Design by Contract 46

Page 47: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts of the derived queries: is_equal

1. The pre-condition of is_equal(other:IMMUTABLE_LIST):BOOLEAN is that the argument list exists (e.g., is not a null pointer).

2. The post-condition of is_equal(other:IMMUTABLE_LIST):BOOLEAN : 1. Both lists might be empty

2. Both lists are not empty, and their heads and tails are equal.

Derived query:

or_else and and_then are Eiffel’s operators for optimized evaluation of or and and

is_equal(other:IMMUTABLE_LIST):BOOLEAN

Purpose: Are the 2 lists, self and other equal in elements and order?

require:

other_exists: other /= null

ensure:

same_content: Result = ( is_empty() and other.is_empty() )

or_else

( ( (not is_empty()) and (not other.is_empty()) )

and then

( head() = other.head()

and

tail().is_equal( other.tail() ) ) )

Evaluated recursively

Software Engineering, 2012 Design by Contract 47

Page 48: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts of the derived queries: sublist

sublist( from_position:INTEGER, to_position:INTEGER ):IMMUTABLE_LIST:

1. The pre-condition requires that the positions are in the [1..count()] range,

and are consistent: from_position is <= to_position+1 (to enable extracting an

empty sublist).

2. The post-condition:

1. If to_position is smaller than from_position

the extracted sublist is empty

2. Otherwise, the extracted list consists of the list elements at positions

from_position to to_position

A new list is constructed

The contract:

Software Engineering, 2012 Design by Contract 48

Page 49: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts of the derived queries: sublist

sublist( from_position:INTEGER, to_position:INTEGER ):IMMUTABLE_LIST

Purpose: A new list, formed from the items at positions from_position to to_position

require:

from_position_large_enough: from_position >= 1

from_position_small_enough: from_position <= to_position + 1

to_position_small_enough: to_position <= count()

ensure:

is_empty_is _consistent_with_from_and_to_position:

Result.is_empty() = ( from_position > to_position )

result_head _is_at _from_position_in_current:

(from_position <= to_position) implies

(Result.head() = item( from_position ) )

result_tail _is_correct_sublist_within_current:

(from_position <= to_position) implies

(Result.tail().is_equal( sublist( from_position+1, to_position ) ) )

To allow zero

sized sublist []

Software Engineering, 2012 Design by Contract 49

Page 50: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Assertion checking modes

In full assertion checking mode, pre-conditions, post-conditions and invariants are

always checked.

For expensive contracts like those of the IMMUTABLE_LIST class, full contract

evaluation is a performance penalty.

Therefore, there are different modes of contract evaluation.

Testing mode: Full evaluation

Working mode: Only pre-condition evaluation

Argument: Once the class is believed to be bug-free,

the post-conditions and invariants are believed to hold as stated.

checking pre-conditions is needed to protect against irresponsible clients

Software Engineering, 2012 Design by Contract 50

Page 51: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts for the class QUEUE

Software Engineering, 2012 Design by Contract 51

Page 52: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

The Queue class Queue is a generic class, with type parameter G: QUEUE of G.

The key features of a SIMPLE_QUEUE class:

SIMPLE_QUEUE

Initialize(capacity:INTEGER)

Put(g:G)

Head:G

remove

G

Software Engineering, 2012 Design by Contract 52

Page 53: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contracts for the class QUEUE

The contracts for QUEUE are based on a query that returns an immutable list of the elements in the queue, in the same order.

Initial class interface:

Features:

Query:

Creation command:

Other commands:

head (): G

Purpose: The item at the head of the queue

initialize ( a_capacity:INTEGER )

Purpose: Initialize a queue to be empty and to have the given capacity (no changing capacities)

put ( g:G )

Purpose: Add g to the tail of the queue

remove ()

Purpose: Remove the item from the head of the queue

Software Engineering, 2012 Design by Contract 53

Page 54: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contract for the remove command(1)

1. The pre-condition of remove() is that the queue is not empty:

Requires a new (basic) query for checking emptiness.

Options: count() or is_empty().

We pick count() – useful for the post-condition

(..The decision is really a matter of class design rather than contracts)

2. The post-condition of remove(): 1. The number of queue items decreases by 1 -is it enough?

2. The i-th element is the (i + 1) -th element in the original queue:

Requires a new items inspection query:

items():IMMUTABLE_LIST that creates an immutable_list of the queue items

Queries:

count()

Purpose: The number of items in the queue

items():IMMUTABLE_LIST Purpose: A new list, created from the queue items, in the same order

Software Engineering, 2012 Design by Contract 54

Page 55: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contract for the remove command (2)

Command:

remove () Purpose: remove the item at the head require: not_empty:

count () > 0

ensure: count_decreased:

count() = count()@pre -1

items_shifted:

items().is_equal( items().tail()) @pre )

Items: [“a”,”b”,”c”].tail : [“b”,”c”] a new list of the right size (2)

Our queue maybe implemented as an array (circular structure)

1

2

3

“a”

“b”

“c”

1

2

3

“b”

“c”

Software Engineering, 2012 Design by Contract 55

Page 56: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

The status of count (1) 1. count() can be expressed in terms of the count feature of the items() list:

count() = items().count()

Therefore, it can be made a derived query:

2. But count() is used in the pre-condition of remove(). Therefore:

count()

Purpose: The number of items in the queue

ensure:

consistent_with_items:

count() = items().count()

require:

not empty:

items().count () > 0

require:

not empty:

count () > 0

Software Engineering, 2012 Design by Contract 56

Page 57: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

The status of count (2) 3. The evaluation of the new not_empty pre-condition implies

evaluation of items().count(), i.e., creation of a new items list and counting its length.

4. Recall: Pre-conditions are evaluated also in working mode: Guideline: Use cheap-to-evaluate queries in pre-conditions.

3. Conclusion: for performance reasons, count should be kept.

4. If count() is implemented as an attribute, it can be constrained

by an invariant:

invariant: count = items().count()

Software Engineering, 2012 Design by Contract 57

Page 58: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contract of the creation command

The QUEUE creation initialize( a_capacity:INTEGER ) command empties a queue (either new or old), with a capacity given by a_capacity

(for simplicity the capacity of a queue cannot be changed).

1. Pre-condition: Positive capacity.

2. Post-condition: 1. The queue should be empty.

2. The queue capacity is the a_capacity.

This post-condition requires a new query about the capacity of a queue:

Creation command:

capacity()

Purpose: The number of items that self can hold

initialize ( a_capacity:INTEGER )

Purpose: Initialize a queue to be empty, with capacity a_capacity

require:

positive_a_capacity: a_capacity > 0

ensure:

empty: count() = 0

capacity_set: capacity() = a_capacity

Software Engineering, 2012 Design by Contract 58

Page 59: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contract for the head query

The head():G - query returns the head item

1. Pre-condition: Queue is not empty

2. Post-condition: Returns the head item.

This is expressed in terms of the head of the items() list.

Therefore, head() is a derived query.

Derived query:

head():G

Purpose: The head item

require:

not_empty: count () > 0 // count>0

ensure:

consistent_with_items:

Result = items().head()

Post condition is expensive

Precondition is cheap

Software Engineering, 2012 Design by Contract 59

Page 60: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Contract for the put command

The put( g:G ) command adds g to the tail of the queue

1. Pre-condition: Queue is not full

2. Post-condition: the number of queue items increases by 1,

the added item is at position count()

Command:

put( g:G )

Purpose: Add g to the tail

require:

not_full: count () < capacity()

ensure:

number_of_items_increases: count() = count()@pre + 1

g_at_tail: items.item( count() ) = g

Software Engineering, 2012 Design by Contract 60

Page 61: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

More derived queries

Explicit queries for emptiness and being full can be added:

Derived queries:

is_empty()

Purpose: Is the queue empty?

ensure:

consistent_with_items.count: Result = (items.count() = 0 )

is_full()

Purpose: Is the queue full?

ensure:

consistent_with_items.count: Result = (items.count() = capacity() )

Software Engineering, 2012 Design by Contract 61

Page 62: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

The final class QUEUE interface

Basic queries: capacity():INTEGER

items() : IMMUTABLE_LIST

Derived queries: head (): G

count(): INTEGER

is_empty(): BOOLEAN

is_full(): BOOLEAN

Creation command: initialize ( a_capacity:INTEGER )

Other commands: put ( g:G )

remove ()

Software Engineering, 2012 Design by Contract 62

Page 63: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Design by Contract and Inheritance

Software Engineering, 2012 Design by Contract 63

Page 64: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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:

Mixed Command:

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:

package_small_enough: p.weight() < 5

ensure:

fast_delivery: Result < t + 3

Software Engineering, 2012 Design by Contract 64

Page 65: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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

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.

deliver( p: Package, t: Time, d: Destination ) : Time

require:

package_small_enough: p.weight() < 8

Software Engineering, 2012 Design by Contract 65

Page 66: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Redefining a pre-condition (2)

If the new pre-condition is:

feature

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

deliver( p: Package, t: Time, d: Destination ) : Time

require:

package_small_enough: p.weight() < 3

Software Engineering, 2012 Design by Contract 66

Page 67: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Redefining a post-condition (1)

If the new post-condition is:

feature

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.

deliver( p: Package, t: Time, d: Destination ) : Time

ensure:

fast_delivery: Result < t + 2

Software Engineering, 2012 Design by Contract 67

Page 68: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Redefining a post-condition (2)

If the new post-condition is:

feature

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

deliver( p: Package, t: Time, d: Destination ) : Time

ensure:

fast_delivery: Result < t + 5

Software Engineering, 2012 Design by Contract 68

Page 69: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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:

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

while

which might not be within the obligation of the delivery service of the sub-class!

DbC languages do not enable strengthening a pre-condition

package_small_enough: p.weight() < 5

or package_small_enough: p.weight() < 8 package_small_enough: p.weight() < 8 reduces to

package_small_enough: p.weight() < 5

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

Software Engineering, 2012 Design by Contract 69

Page 70: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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:

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

while

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

DbC languages do not enable weakening a post-condition

fast_delivery: Result < t + 3

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

fast_delivery: Result < t + 3

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

Software Engineering, 2012 Design by Contract 70

Page 71: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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 else:

package_small_enough: p.weight() < 8

ensure then:

fast_delivery: Result < t + 2

Require of super class

or else require this

ensure of super class

and then ensure this

Software Engineering, 2012 Design by Contract 71

Page 72: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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

Software Engineering, 2012 Design by Contract 72

Page 73: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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 C

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 ) number_of_items_increases: count() = count()@pre

PROBLEM

Software Engineering, 2012 Design by Contract 73

Page 74: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Guarded post-conditions in super-classes

A version with guarded post-conditions:

Now the relaxed subclass can be properly defined:

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

class RELAXED_C extends C put( g: G ) require else g_in_aggregate: has( g ) ensure then g_added: has( g ) number_of_items_unchanged: ( has(g)@pre ) implies count() = count()@pre

OK

Software Engineering, 2012 Design by Contract 74

Page 75: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Guidelines To support redefinition of features, guard each postcondition

clause with its corresponding precondition.

This allows unexpected redefinitions by those developing

subclasses.

Software Engineering, 2012 Design by Contract 75

Page 76: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Frame Rules

Software Engineering, 2012 Design by Contract 76

Page 77: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Change specifications and FrameRules

Frame rules specify what does not change.

Added to post conditions

Post conditions include2 kinds of assertions:

Change specifications – assert that certain thing changes

Frame rules – assert that certain thing remain unchanged put( g:G )

Purpose: Add g to the tail

require:

not_full: count () < capacity()

ensure:

number_of_items_increases:

count() = count()@pre + 1

g_at_tail:

items( count() ) = g

capacity _unchanged:

capacity() = capacity()@pre Software Engineering, 2012 Design by Contract 77

Page 78: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Frame Rules for put Using Immutable

Lists We can add a second frame rule concerning the items in the

queue by adding a 4th assertion to the postcondition on put.

We assert that sublist containing the first 10 items (i.e.,

[email protected]) of 11 items must equal the list containing all

the items that were there before the call (i.e., items@pre).

The frame rule makes use of the is_equal query on lists.

Two lists are equal if they hold the same items.

What if two lists hold references to the same objects but these

objects are in different states?

original_items_unchanged:

items.sublist(1,[email protected]).is_equal(items@pre)

Software Engineering, 2012 Design by Contract 78

Page 79: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Frame Rules for put Using Immutable

Lists Frame rules constrain objects not to change between the time just

before call to a feature and the time just after that call.

There are 2 properties of a list that can change independently:

One object in the list might be replaced by another

The contents of an object might change.

The problem is not solved by changing the meaning of is_equal in

class IMMUTABLE_LIST to check that elements are equal both by

“=“ and by is_equal.

head = other.head and head.is_equal(other.head) and tail.is_equal(other.tail)

Software Engineering, 2012 Design by Contract 79

Page 80: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Frame Rules for put Using Immutable

Lists

The item query returns a list of addresses of the objects that

are the items in the queue.

If the body of put contains a bug and changes the contents of

an item already in the queue the list of addresses will not

have changed and the test that the head of the list after the

call to put is equal to the head before the call succeeds.

1001

2002

3003

“a”

“b”

“c”

1001

2002

3003

“z”

“b”

“c”

500 400

equal

Software Engineering, 2012 Design by Contract 80

Page 81: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Frame Rules for put Using Immutable

Lists At the time of the test, both head and other.head are pointing to the same

object.

We need 2 separate checks:

1. Does queue after put contains the same objects as before put?

2. Do these objects have the same content as before put?

At present, we can only perform the first check.

To be able to perform the second check we need to keep a copy of the

object’s content in the queue before the put, and to compare it with the

content of the object after put.

Use Eiffel’s library feature deep_clone and deep_equal.

The post condition:

Original_items_unchange:

(deep_equal(item.sublist(1, items.count-1), old deep_clone (items)))

Software Engineering, 2012 Design by Contract 81

Page 82: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Frame Rules for put Using “Forall” In the postcondition of put, make sure that the items that

were in the queue are still there and in their logical positions:

Forall i in the range 1 to count, The item at position i is what was at position i before the call

A preprocessor can perform the following tasks to transform “forall” into Eiffel automatically:

Create a collection object of the right size and type

On entry to the put feature, store values of item(i) in this collection

In the postcondition of the put feature, call a Boolean-valued function to compare the stored values of item(i) with values calculated now.

Software Engineering, 2012 Design by Contract 82

Page 83: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Kinds of Frame Rules Regular commands - change the state of the object

A frame rule for put may assert that the items already in a queue are unchanged by putting a new item at the tail.

Creation commands – before these command the object has no particular state

Cannot assert that the state remain unchanged

Basic queries – return a result but not change the state

Assert that calling the query (capacity) does not change the object state ( increment the capacity, change the queue’s values)

Parameters – usually, a routine that is passed a parameter is not supposed to modify the parameter

Assert a postcondition to express this effect.

Software Engineering, 2012 Design by Contract 83

Page 84: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Frame Rules – a practical viewpoint Is it realistic to develop frame rules to cover all these issues?

Suggested approach:

Add frame rules occasionally, particularly where there is evidence that client programmers misunderstand what a feature does and does not do.

Adopt a convention that all classes come with an implicit frame rule, which states that, unless a postcondition asserts that some property changes, it does not change. Unexpected changes then indicates either poor documentation or bugs

In design reviews – check the code against both explicit and implicit frame rules

Software Engineering, 2012 Design by Contract 84

Page 85: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Design by Contract – pros and cons

Software Engineering, 2012 Design by Contract 85

Page 86: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Benefits of Design by Contract Better designs

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.

Software Engineering, 2012 Design by Contract 86

Page 87: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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 debugging

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 defensive programming

Software Engineering, 2012 Design by Contract 87

Page 88: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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 exception

handling.

Software Engineering, 2012 Design by Contract 88

Page 89: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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.

Software Engineering, 2012 Design by Contract 89

Page 90: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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.

Software Engineering, 2012 Design by Contract 90

Page 91: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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 of the same name):

Stopped in object [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

Software Engineering, 2012 Design by Contract 91

Page 92: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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.

Software Engineering, 2012 Design by Contract 92

Page 93: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

JML – Java Modeling Language 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

Software Engineering, 2012 Design by Contract 93

Page 94: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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/

Software Engineering, 2012 Design by Contract 94

Page 95: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

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.

Software Engineering, 2012 Design by Contract 95

Page 96: Software Engineering Design by Contract - BGUfsen141/wiki.files/class-12... · 2013. 10. 16. · Design By Contract The term Design by Contract was coined by Bertrand Meyer while

Software Engineering, 2012 Design by Contract 96