300 likes | 423 Views
Specifications, continued. Announcements. Please, write your name at top of hwN_answers.txt file! HW0 is graded Update hw0.docs directory to get feedback.txt HW1 should be done by Wed Pick your papers in front of Lally 314 Update hw1.docs directory for feedback.txt HW2 is due Friday
E N D
Announcements • Please, write your name at top of hwN_answers.txt file! • HW0 is graded • Update hw0.docs directory to get feedback.txt • HW1 should be done by Wed • Pick your papers in front of Lally 314 • Update hw1.docs directory for feedback.txt • HW2 is due Friday • Harder than previous two, try starting early • As usual, if you have questions, let me know
Announcements • Reflection on HW1 • You: start early! • Me: give more examples in class and in notes • Me: more intuition on guessing loop invariants
Example: Selection Sort i = 0; while (i < a.length) { {Inv: a[0…i-1] is sorted ∧ a[i-1]≤ rest of a} int min = i; int j = i+1; while (j < a.length) { {Inv: a[min] = min(a[i], …, a[j-1]) } if (a[j] < a[min]) min = j; j = j+1; } {Post: a[min] = min(a[i], …, a[a.length-1])} swap(a, i, min); i = i+1 } {Post: a[0…a.lengh-1] is sorted}
Examples and Hints • Great examples in the UW handout • Hint on finding loop invariants • There isn’t a foolproof way… Difficult task • Write down a few iterations and try to find a pattern. We did this with the factorial examples • Look at postcondition. Often the invariant contains a partial result (postcondition is the full result). E.g., the sum of the array elements Fall 14 CSCI 2600, A Milanova
Examples and Hints • For problems 1, 2 • Invariant, pre- and post-conditions, and a proof sketch • For problem 3 • Invariants, pre- and post-conditions. No need to write proofs • For problem 4 • Only algorithms for subtraction and multiplication • Algorithms + invariants, pre- and post-conditions + proofs for evaluation and interpolation
So Far • Specifications • Benefits of specifications • Specification conventions • Javadoc • PoS specifications • JML
Specifications • A specification consists of a precondition and a postcondition • Precondition: conditions that hold before method executes • Postcondition: conditions that hold after method finished execution (if precondition held!)
Specifications • A specification is a contract between a method and its caller • Obligations of the method (implementation of the specification): agrees to provide postcondition if precondition held • Obligations of the caller (user of specification): agrees to meet the precondition and not expect more than the promised postcondition
binarySearch Specification public static int binarySearch(int[] a,int key) Precondition: requires: a is sorted in ascending order Postcondition: modifies: none effects: none returns: i such that a[i] = key if such an i exists -1 otherwise throws: none Fall 14 CSCI 2600, A Milanova (based on slide by Michael Ernst)
Outline • Specifications • Specification Style • Specification Strength • Substitutability • Comparing specifications • By hand • By logical formulas Fall 14 CSCI 2600, A Milanova
Aside: Specifications and Dynamic Languages • In statically-typed languages (C/C++, Java)type signature is a form of specification: List<Integer> listAdd(List<Integer> lst1, List<Integer> lst2) • In dynamically-typed languages (Python, JavaScript), there is no type signature! deflistAdd(lst1, lst2): i = 0 res = [] for j in lst1: res.append(j+lst2[i]); i=i+1 return res
Aside: Specifications and Dynamic Languages • Specifications are imperative. Even more so for dynamically-typed languages! Why? deflistAdd(lst1, lst2): i = 0 res = [] for j in lst1: res.append(j+lst2[i]); i=i+1 return res • Start your spec with type signature. Then fill in the rest of the clauses Fall 14 CSCI 2600, A Milanova
Specification for addLists List<Number> addLists(List<Number> lst1, List<Number> lst2) requires: ? modifies: ? effects: ? returns: ? def addLists(lst1, lst2): i = 0 res = [] for j in lst1: res.append(j+lst2[i]); i=i+1 return res } Fall 14 CSCI 2600, A Milanova
Specification Style • A method is called for its side effects (effects clause) or its return value (returns clause) • It is bad style to have both effects and return • There are exceptions. Can you think of one? • E.g., HashMap.put returns the previous value • E.g., Box.add returns true if successfully added • Main point of spec is to be helpful • Being overly formal does not help • Being too informal does not help either Fall 14 CSCI 2600, A Milanova (slide based on slides by Michael Ernst)
Specification Style • A specification should be • Concise: not too many cases • Informative and precise • Specific (strong) enough: to make guarantees • General (weak) enough: to permit (efficient) implementation • Too weak a spec imposes too many preconditions and/or gives too few guarantees • Too strong a spec imposes too few preconditions and/or gives too many guarantees. Burden on imple-mentation (e.g., is input sorted?); may hinder efficiency Fall 14 CSCI 2600, A Milanova (slide based on slides by Michael Ernst)
Specification Strength • Sometimes, we need to compare specifications (we’ll see why a little later) • “A is stronger than B” means • For every implementation I • “I satisfies A” implies “I satisfies B” • The opposite is not necessarily true • For every client C • “C meets the obligations of B” implies “C meets the obligations of A” • The opposite is not necessarily true
Which One is Stronger? int find(int[] a, int value) { for (inti=0; i<a.length; i++) { if (a[i] == value) return i; } return -1; } • Specification A: requires: a is non-null and value occurs in a returns: the smallest index i such that a[i] = value • Specification B: requires: a is non-null and value occurs in a returns: i such that a[i] = value Fall 14 CSCI 2600, A Milanova (example modified from Michael Ernst)
Which One is Stronger? int find(int[] a, int value) { for (inti=0; i<a.length; i++) { if (a[i] == value) return i; } return -1; } • Specification A: requires: a is non-null and value occurs in a returns: i such that a[i] = value • Specification B: requires: a is non-null returns: i such that a[i] = value or i = -1 if value is not in a Fall 14 CSCI 2600, A Milanova (example modified from Michael Ernst)
Which One is Stronger? String substring(int beginIndex) • Specification A: requires: 0 <= beginIndex < length of this String object returns: new string with same value as the substring beginning at beginIndex and extending until the end of the current string • Specification B: requires:nothing returns: new string with same value as the substring beginning at beginIndex and extending until the end of the current string throws:IndexOutOfBoundsException --- if beginIndex is negative or ≥ length of this String object
Strengthening and Weakening Specification • Strengthen a specification • Require less of client: fewer conditions in requiresclause AND/OR • Promise more to client: effects, modifies, returns • Effects/modifies affect fewer objects • Weaken a specification • Require more of client: add conditions to requires AND/OR • Promise less to client: effects, modifies, returns clauses are weaker, easier to write into code
Ease of Use by Client; Ease of Implementation • Stronger specification is easier to use • Client has fewer preconditions to meet • Client gets more guarantees in postconditions • But stronger spec is harder to implement • Weaker specification is easier to implement • Larger set of preconditions, relieves implementation from burden of handling different cases • Easier to guarantee less in postcondition • But weaker spec is harder to use
Specification Strength • Specification A consists of precondition PA and postcondition QA • Specification B consists of precondition PB and postcondition QB • A is stronger than B if (but not only if!) • PB is stronger than PA (this means, stronger specifications require less). Preconditions are contravariant • QA is stronger than QB (stronger specifications promise more). Postcondtions are covariant
Exercise: Order by Strength Spec A: requires: a non-negative int argument returns: an int in [1..10] Spec B: requires: int argument returns: an int in [2..5] Spec C: requires: true returns: an int in [2..5] Spec D: requires: an int in [1..10] returns: an int in [1..20] Fall 14 CSCI 2600, A Milanova
Group Exercise Spec A: “returns: an integer ≥ its argument” Spec B: “returns: a non-negative integer ≥ its argument” Spec C: “returns: argument + 1” Spec D: “returns: argument2“ Spec E: “returns: Integer.MAX_VALUE” Implementations: Code 1: return arg*2; Code 2: return abs(arg); Code 3: return arg+5; Code 4: return arg*arg; Code 5: return Integer.MAX_VALUE; Fall 14 CSCI 2600, A Milanova (due to Michael Ernst)
Substitutability • Sometimes we use a method where another method is expected. When? • X x; … x.m(). A subclass of X, say Y, may have its own implementation of m, Y.m • The spec of Y.m must be stronger than the spec of X.m! Otherwise, Y.m may work incorrectly when used where X.m was expected • Principle of substitutability • A stronger specification can always be substituted for a weaker one Fall 14 CSCI 2600, A Milanova
BallContainer and Box • Suppose Box is a subclass of BallContainer Spec of Box.add(Ball b) booleanadd(Ball b) requires: b non-null modifies: this Box effects: adds b to this Box if b is not already in and Box is not full returns: true if b is added false otherwise Spec of BallContainer.add(Ball b) booleanadd(Ball b) requires: b non-null modifies: this BallContainer effects: adds b to this BallContainer if b not already in returns: true if b is added false otherwise
BallContainer and Box • A client honoring BallContainer’s spec is justified to expect that b is added: BallContainer c = … … b = new Ball(10); c.add(b) assert(c.contains(b)); • If c was a Box, the assertion may fail! • Box’s spec is not stronger and therefore Box is not substitutable for BallContainer!
Substitutability • In fact, Box is not a true subtype (also called behavioral subtype) of BallContainer • Therefore, it is wrong to make Box a subclass of BallContainer • More on substitutability, Java subtypes and true subtypes later Fall 14 CSCI 2600, A Milanova
Review • “A is stronger than B” means • For every implementation I • “I satisfies A” implies “I satisfies B” • The opposite is not necessarily true! • A larger world of implementations satisfies weaker spec B than stronger spec A • Consequently, a weaker spec is easier to satisfy (implement) • Weaker specs require more AND/OR • Weaker specs guarantee (promise) less