Introduction to: Design by Contract - PowerPoint PPT Presentation

1 / 47
About This Presentation
Title:

Introduction to: Design by Contract

Description:

The rule is that you can only add one engine to the car (adding two is invalid) ... Contracts are 'specs n' checks.' 5. John J. Anthony. Object Oriented ... – PowerPoint PPT presentation

Number of Views:28
Avg rating:3.0/5.0
Slides: 48
Provided by: JA
Category:

less

Transcript and Presenter's Notes

Title: Introduction to: Design by Contract


1
Introduction toDesign by Contract
  • Fall 2005 OOPD
  • John Anthony

2
Design Question
  • You have created a Car class with an operation
    named addEnging(e Engine). The rule is that
    you can only add one engine to the car (adding
    two is invalid). How would you implement this
    rule?
  • allow the addEngine to be called and then throw
    an exception if an engine already exists.
  • return a boolean value indicating the success
    of adding an engine
  • ask the client to check the state of the Car to
    determine if it already has an engine
  • 1 AND 3

3
What is a Contract
  • An entity which describes the obligations between
    2 or more parties which, when fulfilled, provides
    certain rights to the parties.

4
More Specifically
Contracts are specs n checks.
5
Courier Example
6
Example
7
Example
BASIC_CUSTOMER_DETAILS
id CUSTOMER_ID name STRING address
STRING date_of_birth DATE
8
Example
CUSTOMER_MANAGER
BASIC_CUSTOMER_DETAILS
9
Some Design Questions
  • How do I make an id active? By adding a customer
    with that id?
  • If I add a customer whose details match an
    existing customers basic details, what happens?
  • What do I get if I ask for the name of a customer
    whose id is not active?
  • What happens if I set the name for a customer
    whose id is not active?

10
Adding a New Customer
precondition responsibility of client to ensure
expression is true
  • add(a_customer BASIC_CUSTOMER_DETAILS)
  • --add a_customer to the set of customers
  • require
  • id_not_already_active not id_active(a_customer.
    id)
  • ..
  • ensure
  • count_increased count old count 1
  • customer_id_now_active id_active(a_customer.id)

assertion an expression that must evaluate to
true
postcondition responsibility of supplier to
ensure expressions are true after feature
execution
11
Some Answers
  • How do I make an id active? By adding a customer
    with that id?
  • Yes
  • If I add a customer whose details match an
    existing customers basic details, what happens?
  • Not allowed to add a customer whose id equals the
    id of a customer already owned by the manager.
    There are no other constrains on other features
    such as name, address, DOB, etc.

12
Setting the Name of Customer
  • set_name(an_id CUSTOMER_ID, a_name STRING)
  • --set the name of the customer with an_id to
    a_name
  • require
  • id_active id_active(an_id)
  • ..
  • ensure
  • name_set name_for(an_id).is_equal(a_name)

13
Asking for the Name of a Customer
  • name_for(an_id CUSTOMER_ID STRING
  • --the name of the customer with an_id
  • require
  • id_active id_active(an_id)
  • ..

14
More Answers
  • What do I get if I ask for the name of a customer
    whose id is not active?
  • It is illegal to ask for the name of a customer
    whose id is not active.
  • What happens if I set the name for a customer
    whose id is not active?
  • It is illegal to attempt to set the name of a
    customer whose id is not active.

15
Class Invariants
  • A condition that always resolves to True (more
    precisely, it is true whenever you can call a
    feature on the component).

invariant count_never_negative count gt 0
16
Contract Violations
  • What would happen if we (attempt) to add a
    customer whose id is already active?

Stopped in object 0xE96978 Class
CUSTOMER_MANAGER Feature add Problem
Precondition violated Tag id_not_already_active
Arguments a_customer BASIC_CUSTOMER_DETAILS
OXe9697C Call Stack CUSTOMER_MANAGER add was
called by CUSTOMER_MANAGER_UIF change_customer
17
A Simple Stack
STACK
count INTEGER Is_empty BOOLEAN initialize push
(i INTEGER) pop(out I INTEGER)
18
Principle 1
  • Separate commands from queries
  • Queries return a result but do not change the
    visible properties of the object. Commands might
    change the object but do not return a result.

19
Principle 1
  • Lets write the contract for the push command

push (I INTEGER) --push i onto the top of
the Stack . ensure top_is_i i ?????
push (I INTEGER) --push i onto the top of
the Stack . ensure top_is_i i pop
20
Principle 1
push (I INTEGER) --push i onto the top of
the Stack . ensure top_is_i i pop
push (I INTEGER) --push i onto the top of
the Stack . ensure top_is_i top i
21
Commands vs. Queries
features
routines
attributes
QUERIES
procedures
functions
creation
other
COMMANDS
22
The Revised Stack
STACK
ltltQueriesgtgt count INTEGER --the number of items
on the stack item INTEGER --the top
item Is_empty BOOLEAN --is the stack
empty? ltltCreation Commandsgtgt Initialize ltOther
Commandsgtgt put (i INTEGER) --put I onto the
top of stack remove --remove the top item
STACK
Eiffel Naming Conventions
count INTEGER Is_empty BOOLEAN initialize push
(i INTEGER) top INTEGER delete
23
Principle 2
  • Separate basic queries from derived queries
  • Derived queries can be specified in terms of
    queries.

24
Principle 3
  • For each derived query, write a postcondition
    that specifies what result will be returned in
    terms of one or more basic queries.
  • Then, if we know the values of the basic queries,
    we also know the values of the derived queries.

25
Principle 2 3
Principle 2 Since is_empty is derived from count
Is_empty BOOLEAN --does the stack contain no
items . ensure consistent_with_count Result
(count 0)
Principle 3 Since postcondition is defined in
terms of count
The assertion is defined in terms of the count
query. if(count gt 0) Result false else Result
true
26
Revised Stack
STACK
ltlt Basic Queriesgtgt count INTEGER --the number
of items on the stack item INTEGER --the top
item ltltDerived Queriesgtgt Is_empty
BOOLEAN --is the stack empty? ltltCreation
Commandsgtgt Initialize ltOther Commandsgtgt put (i
INTEGER) --put I onto the top of
stack remove --remove the top item
27
Principle 4
  • For each command, write a postcondition that
    specifies the value of every basic query.
  • Taken together with the principle of defining
    derived queries in terms of basic queries, this
    means that we know the total visible effect of
    each command.

28
Principle 4
put (I INTEGER) --push I onto the top of
the stack . ensure count_increased count
old count 1 g_on_top item i
Count increased by 1
Top of stack equal to i
29
Principle 4
initialize --initialize the stack to be
empty . ensure stack_contains_zero_items
count 0
count set to 0
What about the second basic query item????
30
Principle 4
item --return the top item of the
stack require stack_not_empty count gt 0
Count must be greater than 0 in order to call item
  • Now, our contract on initialize ensures that
  • the value of count is zero
  • the top item has no value

31
Principle 4
remove --delete the top item require stack_not
_empty count gt 0 ensure count_decreased
count old count - 1 top_item_removed Result
old item
Ensures that we do not try to remove an item from
an empty stack.
32
Principle 5
  • For every query and command, decide on a suitable
    precondition.
  • Preconditions constrain when clients may call the
    queries and commands.

33
Principle 6
  • Write invariants to define unchanging properties
    of objects.
  • Concentrate on properties that help the reader
    build an appropriate conceptual model of the
    abstraction that the class embodies.

34
Principle 6
invariant count_never_negative count gt 0
35
Contracts and Inheritance
  • How are contracts inherited from parent classes.
  • How can contracts be redefined?
  • How can we construct subclasses that respect the
    parents contract?

36
Back to Courier Example
Remember.
37
Courier Class
class COURIER feature deliver (p PACKAGE, d
DESTINATION) --deliver package to
destination require --weight of package p
does not exceed 5 lbs. . ensure --pack
age delivered within 3 working hours . end
38
Remember Polymorphism?
Courier
Client
deliver()
2. The client thinks it is using a deliver
service from a regular kind of courier.
3. But the service is actually provided by a
different kind of courier.will the service be
acceptable to the client?
Different_Courier
1. A client is given access to a courier object
deliver()
ltltinstance ofgtgt
a_client Client
a_courier Different_Courier
39
Consider New Preconditions
  • weight of package must not exceed 8 lbs
  • weight of package must not exceed 3 lbs
  • weight of package must not exceed 2 lbs

Which precondition(s) are acceptable?
40
Consider New Postconditions
  • package will be delivered within 2 hours
  • package will be delivered in 3 working hours
  • package will be delivered in 5 working hours

Which postcondition(s) are acceptable?
41
Different_Courier
class DIFFERENT_COURIER feature deliver (p
PACKAGE, d DESTINATION) --deliver package
to destination require else --weight of
package p does not exceed 8 lbs. . ensure
then --package delivered within 2 working
hours . end
42
Complete Precondition
deliver (p PACKAGE, d DESTINATION) --de
liver package to destination require --weight
of package p does not exceed 5 lbs. require
else --weight of package p does not exceed 8
lbs.
Weight of package does not exceed 5 lbs. or
else Weight of package does not exceed 8 lbs.
43
Complete Postcondition
deliver (p PACKAGE, d DESTINATION) --de
liver package to destination ensure --package
delivered within 3 working hours ensure
then -- package delivered within 2 working
hours
Package delivered within 3 working hours and
then Package delivered within 2 working hours
44
Benefits of Design by Contract
  • Benefits include
  • Achieving better designs
  • Improving reliability
  • Getting better documentation

45
Better Designs
  • More Systematic Designs
  • Designers are encouraged to think about such as
    matters as preconditions and postconditions
    resulting in concepts being more explicit.
  • Clearer Designs
  • The obligations and benefits are shared between
    the client and the suppler and are clearly
    stated.
  • Simpler Designs
  • Limitations on the use of a routine are clearly
    expressed in its precondition, and the
    consequences of calling it illegally are clear.
  • Systematic Use of Exceptions
  • Exceptions are thrown when a routine is used
    illegally (false precondition) or when a routine
    fails to fulfill its contract (false
    postcondition)and nothing in between

46
Improved Reliability
  • Better Understood and Hence More Reliable Code
  • Separates the contract code from the
    implementation code. Requires the implementer to
    think about the specification from two
    perspectives.
  • Better Tested and Hence More Reliable Code
  • Assertions are checked at runtime, thereby
    testing that routines fulfill their stated
    contracts. (A formal approach to test-driven
    development)

47
Better Documentation
  • Clearer Documentation
  • Contracts form part of the public, or client,
    view of a class..
  • More Reliable Documentation
  • Assertions are checked at runtime, thereby
    testing that the stated contracts are consistent
    with what the routines actually do.
Write a Comment
User Comments (0)
About PowerShow.com