Designing for Correctness

download Designing for Correctness

of 47

Transcript of Designing for Correctness

  • 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

    [email protected]

    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

    [email protected]

    2 of 47

    Contact Info

    James C. McKim, Jr.

    CIS Department

    Rensselaer at Hartford

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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

    [email protected]

    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