designing for correctness
TRANSCRIPT
-
8/2/2019 Designing for Correctness
1/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
1 of 47
Advanced Programming ByContract: Designing forCorrectness
TOOLS Pacific, 1999
Melbourne, Australia
-
8/2/2019 Designing for Correctness
2/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
2 of 47
Contact Info
James C. McKim, Jr.
CIS Department
Rensselaer at Hartford
Much of the work presented here was done incollaboration with Richard Mitchell, University of
Brighton.
-
8/2/2019 Designing for Correctness
3/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
3 of 47
Overview
What is Programming by Contract?
How do we use Programming by Contract to designcorrect classes?
Cashier example.
Fully checkable contracts: The power of Recursion
Reductionism and Nondeterminism
Conclusion
Appendix
-
8/2/2019 Designing for Correctness
4/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
4 of 47
What it is
Object Oriented Systems are made up ofObjects.
An Objects behavior is specified by a Class.
Classes consist ofFeatures.
A Feature is either a Commandor a Query or both.
A command may change the state of an object, whilea query returns information about the state of the
object.
-
8/2/2019 Designing for Correctness
5/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
5 of 47
What it is (Contd)Programming by contract is a means of rigorouslyspecifying what a feature provides.
In particular you can use it to:
1. Specify when it is appropriate to call a feature(Precondition).
2. Specify what a feature accomplishes when it iscalled correctly (Postcondition).
Collectively, preconditions and postconditions are
called assertions.
-
8/2/2019 Designing for Correctness
6/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
6 of 47
What It Is (Contd)If class A uses the services of class B we say A is theclient of the supplier B.
The contract between the client and the supplier maybe stated as:
The supplier guarantees the postcondition of any
feature the client invokes, providedthe clientguarantees the precondition.
-
8/2/2019 Designing for Correctness
7/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
7 of 47
Exampleclass STACK[ G ]
top : G
require depth > 0
depth : INTEGER
capacity : INTEGER
push( x : G )
require depth < capacity
ensure top = x ; depth = old depth + 1
...
-
8/2/2019 Designing for Correctness
8/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
8 of 47
Exampleclass CLIENT
stk : STACK[STRING]
some_feature is-- need to push Mary onto the stack but were-- unsure if theres room.
if stk.depth < stk.capacity thenstk.push( Mary )
else-- alternative action
end
-
8/2/2019 Designing for Correctness
9/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
9 of 47
How to Use ItPrinciple 1: Separate commands and queries.
Discussion: You must at least provide some pure
queries to have a chance at runtime checkability.
Justification: Separation of concerns.
Violations: If speed is of the essence (e.g. in a hardreal time system) it may be necessary to combinecommands and queries in some instances.
Example: Stack
-
8/2/2019 Designing for Correctness
10/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
10 of 47
How to Use It (Contd)Principle 2: Do not be limited by your language. Forexample feel free to use universal and existentialquantifiers as need be.
Justification: The goal is a complete specificationthat is readable by technical people. Its nice if thespecification is compilable, but its not necessary.
Example: in class SET[ G ] the following assertion
for_all x : G (not has( x ))
states that the set has no elements i.e. its empty.
-
8/2/2019 Designing for Correctness
11/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
11 of 47
How to Use It (Contd)Principle 3: Identify a basic specification set of purequeries. Every other feature in the class must becompletely defined in terms of the queries in thespecification set.
Justification: Provides a controlled means ofrigorously specifying many features in terms of a
few. Once the specification set is understood, clientscan quickly comprehend any feature in the class.
-
8/2/2019 Designing for Correctness
12/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
12 of 47
How to Use It (Contd)class SET[ G ]
make( c : INTEGER )
cardinality, capacity : INTEGER
insert( x : G )
delete( x : G )
is_empty : BOOLEAN
is_full : BOOLEAN
has( x : G ) : BOOLEAN
-
8/2/2019 Designing for Correctness
13/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
13 of 47
How to Use It (Contd)-- specification set: has, cardinality, capacity
cardinality, capacity : INTEGER
has( x : G ) : BOOLEAN
make( c : INTEGER )requirec >= 0
ensurecardinality = 0 ; capacity = c ;for_all x : G (not has(x))
-
8/2/2019 Designing for Correctness
14/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
14 of 47
How to Use It (Contd)insert( x : G )
require not has( x ) ; cardinality < capacity
ensure has( x ) ; cardinality = old cardinality + 1capacity = old capacity ;for_all y : G (y/=x implies has( y ) = old has( y ))
delete( x : G )require has( x )ensure not has( x ) ; cardinality = old cardinality - 1capacity = old capacity ;
for_all y : G (y/=x implies has( y ) = old has( y ))
-
8/2/2019 Designing for Correctness
15/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
15 of 47
How to Use It (Contd)Note: Including has( x ) and not has( x ) in thepreconditions ofinsert and remove, respectively is
debatable. Can we remove them?
is_empty : BOOLEANensure Result = (cardinality = 0)
is_full : BOOLEAN
ensure Result = (cardinality = capacity)
-
8/2/2019 Designing for Correctness
16/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
16 of 47
How to Use It (Contd)We can add new commands merely by expressing
their effects on the specification set.
expand( c : INTEGER )require c > capacityensure cardinality = old cardinality ; capacity = c
for_all x : G (has(x) = old has( x ))
contract( c : INTEGER )require c < capacity ; c > cardinality
ensure cardinality = old cardinality ; capacity = cfor_all x : G (has(x) = old has( x ))
-
8/2/2019 Designing for Correctness
17/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
17 of 47
Cashier ExampleThe CASHIER class is supposed to model asupermarket cashier in a simulation of the
supermarket.
Customers always enter the cashier line at the end ofthe line, but may leave from anywhere. However it is
assumed that the customer currently being servedwill not leave until completion of service.
It is part of CASHIERs responsibilities to stamp
each Customers arrival and departure time.
-
8/2/2019 Designing for Correctness
18/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
18 of 47
Cashier Example(Contd)-- specification set: customer, length, clock
length : INTEGERclock : CLOCK
customer( i : INTEGER ) : CUSTOMER
require i >= 1 ; i
-
8/2/2019 Designing for Correctness
19/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
19 of 47
Cashier Example(Contd)insert( c : CUSTOMER ) -- New customer arrivesensure
length = old length + 1 ; c.start_time = clock.timecustomer( length ) = c ; clock = old clockfor_all i, 1..old length
(customer( i ) = old customer( i ))
remove( i : INTEGER ) -- ith customer leaves.require i >= 2; i
-
8/2/2019 Designing for Correctness
20/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
20 of 47
Cashier Example(Contd)finish -- Finish processing current customer.require length >= 1
ensure length = old length - 1 ; clock = old clockold customer( 1 ).finish_time = clock.timefor_all i, 1..length
(customer( i ) = old customer( i+1 ))
current_customer : CUSTOMERrequire length >= 1ensure Result = customer( 1 )
no_customers : BOOLEANensure Result = (length = 0 )
-
8/2/2019 Designing for Correctness
21/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
21 of 47
Fully Checkable ContractsNot easy to come by with todays technology.
If we take a top, depth, and capacity as thespecification set for a STACK, then we can fullyspecify push.
push( x : G )require depth < capacityensure depth = old depth + 1 ; top = x ;
capacity = old capacity
-
8/2/2019 Designing for Correctness
22/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
22 of 47
Fully Checkable STACK
But pop is not so easy.
poprequire depth > 0ensure depth = old depth - 1 ; capacity = old capacity
top = ??????
-
8/2/2019 Designing for Correctness
23/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
23 of 47
Fully Checkable STACK (Item)
One solution is to add an item query and useuniversal quantifiers.
The specification set is now item, depth, and capacity,and the relevant parts of the specification follow.
item( i : INTEGER ) : Grequire i >= 1 ; i 0ensure Result = item( depth )
-
8/2/2019 Designing for Correctness
24/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
24 of 47
Fully Checkable STACK (Item)
push( x : G )require depth < capacity
ensure depth = old depth + 1 ;capacity = old capacityitem( depth ) = xfor_all i, 1..depth - 1 (item( i ) = old item( i ))
poprequire depth > 0ensure depth = old depth - 1
capacity = old capacityfor_all i, 1..depth (item( i ) = old item( i ))
-
8/2/2019 Designing for Correctness
25/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
25 of 47
Fully Checkable STACK (Item)
Advantages:
Easy to read, complete specification.
Disadvantages:
Checkable by few, if any, existing languages. Notethe problem of defining old in the scope of thequantifier.
Is this still a STACK?
A d d P i b C t t
-
8/2/2019 Designing for Correctness
26/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
26 of 47
Fully Checkable STACK (Contd)
For an alternative, consider the mathematical, ADT,definition of a Stack.
new -> empty
push( x ) -> not empty
pop( push( x ) ) is the identity function
top( push( x ) ) = x
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
27/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
27 of 47
Fully Checkable STACK (Contd)
Proofs that implementations of Stacks accuratelyrepresent the above, involve definitions of equality of
stack objects and require either recursion orinduction.
Can we write the specification in such a way that
recursion will provide the checkability for us?
We will need to define equality and we will needqueries that produce stacks so we can verify equality
at appropriate times.
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
28/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
28 of 47
Fully Checkable STACK (Contd)
In particular well need to be able to refer to a newstack thats equal to the current one with:
1. One additional element, the pushed element.
2. One less element, the popped element.
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
29/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
Tools Pacific, 1999
29 of 47
Fully Checkable STACK (Contd)
minus_top( x : G ) : STACK[ G ]require not is_empty
-- This will be a specifier, so no postcondition isnecessary.
plus_top( x : G ) : STACK[ G ]
ensurenot Result.is_emptyResult.top = xResult.minus_top.is_equal( Current )
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
30/47
g g y
Tools Pacific, 1999
30 of 47
Fully Checkable STACK (Contd)
is_equal( other : STACK[ G ] ) : BOOLEANrequire other /= Void
ensureResult =(is_empty and other.is_empty) or
-- Both are empty, or
((not is_empty and not other.is_empty) and then-- Neither is empty and(top = other.top and -- Tops are the same, andminus_top.is_equal( other.minus_top) ))
-- Everything else is the same.
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
31/47
Tools Pacific, 1999
31 of 47
Fully Checkable STACK (Contd)
Basic Specifiers are is_empty, top, and minus_top.
is_equalis an Auxiliary Specifier. That is, its definedin terms of the Basics, but its convenient to use it tospecify other features.
The significant features can now be fully specified asfollows:
make
ensure is_empty
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
32/47
Tools Pacific, 1999
32 of 47
Fully Checkable STACK (Contd)
push( x : G )ensure not is_empty ; top = x ;
minus_top.is_equal( old clone( Current ) )
poprequire not is_empty
ensureis_equal( old minus_top )
depth : INTEGER
ensureis_empty implies Result = 0not is_empty implies Result = minus_top.depth + 1
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
33/47
Tools Pacific, 1999
33 of 47
Fully Checkable STACK (Contd)
We have a complete, fully checkable, specificationusing todays technology.
If we allow ourselves universal quantifiers, we caninclude some interesting, though not checkable,invariants.
for_all x : G (not plus_top( x ).is_empty)for_all x : G (plus_top( x ).top = x)for_all x : G (is_equal( plus_top( x ).minus_top))
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
34/47
Tools Pacific, 1999
34 of 47
Fully Checkable Classes
Many other data structures, particularly the linearones, will yield to the same techniqes.
As will variations of these, such as CASHIER. Leftas an exercise.
An interesting nonlinear structure is SET.
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
35/47
Tools Pacific, 1999
35 of 47
SET Revisited
Note that while we included cardinality as a basicspecifier earlier, arguably we shouldnt need it. If we
can answer the has question in every case, we knoweverything there is to know about the Set.
In fact, if we think about set operations such as
union, intersection, and difference, we quickly seethat it is not always an easy task to specify howcardinality changes.
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
36/47
Tools Pacific, 1999
36 of 47
SET Revisited (Contd)
Wed like to treat cardinality similarly to the way wetreated depth in the STACK class.
But this requires some distinguishable element of theSet to play the role oftop.
We choose to call this element choice.
This element may be nondeterministically chosen,however, it must be a pure query.
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
37/47
Tools Pacific, 1999
37 of 47
SET Revisited (Contd)
Since choice is an arbitrary nondeterministicelement of the set, we need not specify its precise
value.
choice : Grequire
there_exists x : G (has( x )) -- not emptyensurehas( Result ) -- nondeterministic
Note: Depends only on has.
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
38/47
Tools Pacific, 1999
38 of 47
SET Revisited (Contd)
Just as choice is the analog oftop, well needminus_choice as the analog ofminus_top.
minus_choice : SET[ G ]requirenot is_empty
ensurenot Result.has( choice )for_all x : G
(choice /= x implies (has( x ) = Result.has( x )))
Note: Depends on has, choice, and is_empty.
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
39/47
Tools Pacific, 1999
39 of 47
SET Revisited (Contd)
Basic specifiers: hasAuxiliary specifiers (1): choice, is_empty
Auxiliary specifiers (2): minus_choice
Sample features follow:
has( x : G ) : BOOLEAN-- Basic specifier
is_empty : BOOLEAN
ensureResult = for_all x : G (not has( x ))
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
40/47
Tools Pacific, 1999
40 of 47
SET Revisited (Contd)
makeensure is_empty
cardinality : INTEGERensure
is_empty implies Result = 0
not is_empty impliesResult = 1 + minus_choice.cardinality
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
41/47
Tools Pacific, 1999
41 of 47
SET Revisited (Contd)
is_equal( other : SET[ G ] )require other /= Void
ensureResult = for_all x : G (has( x ) = other.has( x ))
merge( other : SET[ G ] )
require other /= Voidensurefor_all x : G
(has( x ) = (old has( x ) or other.has( x )))
Note that theres no need to mention cardinality ineither of the above.
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
42/47
Tools Pacific, 1999
42 of 47
SET Revisited (Exercise for the
Reader)
Is there a way to make better use ofchoice and
minus_choice so that we can use recursion to reducethe use of quantifiers thus providing bettercheckability?
Answer: Yes, but its messy. See appendix.
-
8/2/2019 Designing for Correctness
43/47
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
44/47
Tools Pacific, 1999
44 of 47
Appendix: Some hints on
specifying Set in a checkable
fashion
Try to mimic the recursive spec of Stack as best youcan.
Basic specification set becomes: choice,minus_choice, and is_empty.
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
45/47
Tools Pacific, 1999
45 of 47
Appendix (Contd)
We can define even something as basic as has fromthese:
has( x : G ) : BOOLEANensure
is_empty implies not Result
not is_empty and choice = x implies Resultnot is_empty and choice /= x impliesResult = minus_choice.has( x )
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
46/47
Tools Pacific, 1999
46 of 47
Appendix (Contd)
In the case of the Stack, the intuitive notion of equalStacks matched the specification set. That is, the twostacks being compared needed to agree on is_empty,top, and minus_top.
In the case of the Set, the intuitive notion of equality
is has the same elements, and any notion ofchoiceis irrelevant.
We probably need a second notion of equality that
matches the specification set, is_specifically_equal(?).
A d v a n c e d P r o g r a m m i n g b y C o n t r a c t
-
8/2/2019 Designing for Correctness
47/47
Tools Pacific, 1999
47 of 47
Appendix (Contd)
And well need more layers of specifiers. Heres whatmy version has.
Basic specification set:is_empty, choice, minus_choice
Auxiliary specification (1): is_specifically_equal, has
Auxiliary specification (2):plus, specific_clone, is_subset_of
Auxiliary specification (3): minus, is_equal