Liskov 2-3

advertisement
Procedural Abstraction and
Design by Contract
Paul Ammann
Information & Software Engineering
SWE 619
Software Construction
cs.gmu.edu/~pammann/
SWE 619
© Paul Ammann
Benefits of Abstraction


Locality
– The implementation of an abstraction can be read or
written without needing to examine the implementations
of any other abstractions
Modifiability
– An abstraction can be reimplemented without requiring
changes to any abstractions that use it
SWE 619
© Paul Ammann
2
Abstraction by Specification
Abstraction
Implementation 1
SWE 619
…
© Paul Ammann
Implementation N
3
Specifications


Way to Define Abstractions
Formality
– As much as is useful
– More than just English
– Typically less than a language with a formal semantics
– We will be close to industry standard (ie Javadoc)
– Not intended to be a programming language!
SWE 619
© Paul Ammann
4
Parts of a Procedural Specification
Precondition: Anything missing?
What happens in other languages? (eg C++)
Header
public static int sortedSearch (int[]a, int x)
// Requires: a is sorted in ascending order
// Effects:
if x is in a returns an index where
// x is stored; otherwise, returns -1
Postcondition (examples?)
SWE 619
© Paul Ammann
5
Another Example
No Precondition! (Precondition equals “true”)
public static int search (int[]a, int x)
// Effects:
if x is in a returns an index where
// x is stored; otherwise, returns -1
Underdetermined – what happens if x is in a more
than once?
SWE 619
© Paul Ammann
6
Yet Another Example
Still no precondition (what if a is null?)
Notice the “Modifies” clause
Notice implicit treatment of duplicates
public static void sort (int[] a)
// Modifies: a
// Effects:
rearranges the elements of a into
// ascending order
// E.g. if a = [3,1,6,1] before the call, then
//
a = [1,1,3,6] after the call
Alternate notation:
// E.g. if a = [3,1,6,1], then a_post = [1,1,3,6]
SWE 619
© Paul Ammann
7
Yet Another Example
Procedures may modify variables that are not
explicit arguments
public static void copyLine()
// Requires: System.in contains a line of text
// Modifies: System.in and System.out
// Effects:
Reads a line of text from System.in,
// advances the cursor in System.in to the end of
// the line, and writes the line on System.out
SWE 619
© Paul Ammann
8
Specifications and Implementations
 Minimality
– minimal means fewer constraints on behavior (what does
this say about the postcondition?)
 Underdetermined
behavior
– More than one possible result per input allowed
 Deterministic
implementation
– Only one result per input produced
 Generality
– More general if specification can handle a large class of
inputs. (What does this say about the precondition?)
SWE 619
© Paul Ammann
9
Total vs. Partial Procedures
A
procedure is total if its behavior is
specified for all possible inputs.
 A partial procedure always has a
precondition.
 Partial procedures are less safe than total
procedures.
 Exception handling can be used to eliminate
preconditions (more in next lecture…).
SWE 619
© Paul Ammann
10
Bertrand Meyer’s View:
Design by Contract
A
programmer’s job is to produce solutions,
not programs.
 Software should be reliable.
 Type safety, garbage collection, etc…
– These are good
– But they are not enough
 Correctness
is a relative notion
– A program is correct relative to a specification
SWE 619
© Paul Ammann
11
What does a Contract Look Like?
 Consider the triple: {P} S {Q}
– P is the precondition (Requires clause)
– Q is the postcondition (Effects clause)
– S is the program text
 The
Customer (client) is obligated to
establish P.
 The Implementor (service) may assume P
 The Customer is entitled to Q
 The Implementor is obligated to provide Q
 That’s it!
SWE 619
© Paul Ammann
12
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, then the Service is
wrong (The service has a bug).
 The Client can’t do the Service’s job!
 The Service can’t do the Client’s job!
SWE 619
© Paul Ammann
13
Application of Contract Model to
Debugging
 Suppose
you are fixing a fault in a program.
– What justification is there for a proposed change?

Example Context:
code considered correct
..... {P}
code identifed as wrong vs. proposed correct code
..... {Q}
more code considered correct
SWE 619
© Paul Ammann
14
Example
//Effects: if arr is null throw NPE else return the
number of occurrences of 0 in arr
public static in numZero (int[] arr) {
int count = 0;
{inv: count has # zeros in arr[0..-1]}
for (int i=1; i < arr.length; i++) {
Note the bug!
{inv: count has # zeros in arr[0..i-1]}
if (arr[i] == 0) {count++}
}
return count;
}
SWE 619
© Paul Ammann
15
What does the Client like?
 Since
preconditions are Client obligations,
the Client would prefer not to have any!
 From the Client’s perspective, “true” is the
best precondition. In general, weaker
preconditions are better.
 The Client is happy to have any
postcondition that is strong enough to meet
the Client’s needs.
SWE 619
© Paul Ammann
16
What does the Server like?
 Since
preconditions are Server benefits, the
Server would prefer to have lots of them!
 From the Server’s perspective, “false” is the
best precondition. In general, stronger
preconditions mean an easier job with the
implementation.
 The Server prefers weak postconditions.
Each additional constraint in a postcondition
is an additional obligation on the Server.
SWE 619
© Paul Ammann
17
Who should get preference?
 In
Business, the Customer is thought to be
“always right” This is a good model for
software as well:
 Tradeoffs should generally be made in favor
of the client. That is
– minimize preconditions
– provide usefully strong postconditions
 But
SWE 619
there are limits…
© Paul Ammann
18
Problems with Eliminating
Preconditions
 Forcing
the Server to handle “weird” cases
can lead to inefficient, bulky (read “error
prone”) code.
 For “local” use, therefore, preconditions can
be extremely powerful (and appropriate).
 Example: Consider the “partition” method
in a quicksort routine (Liskov p. 49). It
would be weird to handle the case where the
array indices were out of bounds.
SWE 619
© Paul Ammann
19
More Problems with Eliminating
Preconditions
 What
if the Implementer can’t provide a
good “default” (ie Defensive Programming)?
 Consider the following (horrible) code:
public double sqrt (double x) {
if (x < 0) {
handle problem somehow
return some value (what?)
}
else {
proceed with normal square root computation
return y such that y*y is approximately x
}
}
SWE 619
© Paul Ammann
20
Dissecting the Square Root Example
 What
could possibly be a correct “default”?
– Printing an error message?
• Not a comforting thought to certain end users (ie
pilots).
 What
could possibly be a reasonable return
value?
 The Lesson: The Server is not in a position
to define behavior. That’s the Client’s job.
(through the contract mechanism).
SWE 619
© Paul Ammann
21
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.
 So,
Meyer’s advice is, “Don’t do it!”
– Your mileage may vary
– Think about this in the context of preconditions and
exception handling.
 What
SWE 619
are the implications for security?
© Paul Ammann
22
Download