Specifications.

Slides:



Advertisements
Similar presentations
Automated Theorem Proving Lecture 1. Program verification is undecidable! Given program P and specification S, does P satisfy S?
Advertisements

Cs205: engineering software university of virginia fall 2006 Specifying Procedures David Evans
Addressing the Challenges of Current Software. Questions to Address Why? What? Where? How?
Identity and Equality Based on material by Michael Ernst, University of Washington.
The Substitution Principle SWE 332 – Fall Liskov Substitution Principle In any client code, if subtype object is substituted for supertype object,
Reasoning About Code; Hoare Logic, continued
Specifications, continued. Announcements HW1 was due today at 2 HW2 will be out tonight No class on Tuesday, class next Friday Quiz 2 today Spring 15.
ISBN Chapter 3 Describing Syntax and Semantics.
1 Design by Contract Building Reliable Software. 2 Software Correctness Correctness is a relative notion  A program is correct with respect to its specification.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 18 Program Correctness To treat programming.
CS 330 Programming Languages 09 / 16 / 2008 Instructor: Michael Eckmann.
Describing Syntax and Semantics
Specifications. Announcements HW1 is due Friday To submit answers, commit Error in HW1: In problem 8, part 2 z = 0 should be z = MAX_INT 2.
1 ES 314 Advanced Programming Lec 2 Sept 3 Goals: Complete the discussion of problem Review of C++ Object-oriented design Arrays and pointers.
Subclasses and Subtypes CMPS Subclasses and Subtypes A class is a subclass if it has been built using inheritance. ▫ It says nothing about the meaning.
Cs205: engineering software university of virginia fall 2006 Semantics and Specifying Procedures David Evans
Computer Science 340 Software Design & Testing Design By Contract.
Procedure specifications CSE 331. Outline Satisfying a specification; substitutability Stronger and weaker specifications - Comparing by hand - Comparing.
1 Abstraction  Identify important aspects and ignore the details  Permeates software development programming languages are abstractions built on hardware.
SWE 619 © Paul Ammann Procedural Abstraction and Design by Contract Paul Ammann Information & Software Engineering SWE 619 Software Construction cs.gmu.edu/~pammann/
111 Protocols CS 4311 Wirfs Brock et al., Designing Object-Oriented Software, Prentice Hall, (Chapter 8) Meyer, B., Applying design by contract,
Low-Level Detailed Design SAD (Soft Arch Design) Mid-level Detailed Design Low-Level Detailed Design Design Finalization Design Document.
CSE 331 Software Design & Implementation Hal Perkins Autumn 2012 Specifications (Slides by Mike Ernst) 1.
(c) University of Washington15-1 CSC 143 Java List Implementation via Arrays Reading: 13.
© Paul Ammann, 2008 Design by Contract Paul Ammann CS/SWE 332.
Type Abstraction Liskov, Chapter 7. 2 Liskov Substitution Principle In any client code, if the supertype object is substituted by a subtype object, the.
Type Abstraction SWE Spring October 05Kaushik, Ammann Substitution Principle “In any client code, if supertype object is substituted.
ANU COMP2110 Software Design in 2003 Lecture 10Slide 1 COMP2110 Software Design in 2004 Lecture 12 Documenting Detailed Design How to write down detailed.
Programming Techniques Lec03 Procedural Abstraction Software Engineering Fall 2005.
SWE 4743 Abstract Data Types Richard Gesick. SWE Abstract Data Types Object-oriented design is based on the theory of abstract data types Domain.
CSE 143 Lecture 4 More ArrayIntList : Pre/postconditions; exceptions; testing reading: slides created by Marty Stepp and Hélène Martin
Building Java Programs Chapter 15 Lecture 15-2: testing ArrayIntList; pre/post conditions and exceptions reading:
CSE 331 Software Design & Implementation Dan Grossman Winter 2014 Lecture 4 - Specifications (Based on slides by Mike Ernst, Hal Perkins)
1 CSE 331 Specifications slides created by Marty Stepp based on materials by M. Ernst, S. Reges, D. Notkin, R. Mercer, Wikipedia
Reasoning and Design (and Assertions). How to Design Your Code The hard way: Just start coding. When something doesn’t work, code some more! The easier.
CSE 374 Programming Concepts & Tools Hal Perkins Fall 2015 Lecture 17 – Specifications, error checking & assert.
Modular Decomposition, Abstraction and Specifications
EECE 310: Software Engineering
Input Space Partition Testing CS 4501 / 6501 Software Testing
CSE 374 Programming Concepts & Tools
Specifications Liskov Chapter 9
CSE 331 Software Design & Implementation
Type Abstraction SWE Spring 2009.
Testing UW CSE 160 Spring 2018.
Design by Contract Fall 2016 Version.
Testing, conclusion Based on material by Michael Ernst, University of Washington.
CSE 331 Software Design and Implementation
Preconditions, Postconditions & Assertions
Reasoning About Code; Hoare Logic
Testing UW CSE 160 Winter 2016.
Reasoning about Loops, Conclusion
Specifications, conclusion. Abstract Data Types (ADTs)
Exam 1 Review.
Programming Languages 2nd edition Tucker and Noonan
Type Abstraction Liskov, Chapter 7.
Hoare-style program verification
CSE 331 Software Design & Implementation
Semantics In Text: Chapter 3.
Java Reasoning About Code
CSE 143 Lecture 4 More ArrayIntList:
Protocols CS 4311 Wirfs Brock et al., Designing Object-Oriented Software, Prentice Hall, (Chapter 8) Meyer, B., Applying design by contract, Computer,
IMPORTANT NOTE Some parts of these section slides deal with null ints. This was a mistake, as primitives cannot be null. These issues have been corrected.
CSE 331 Software Design & Implementation specifications
Java Modeling Language (JML)
Assertions References: internet notes; Bertrand Meyer, Object-Oriented Software Construction; 4/25/2019.
Computer Science 340 Software Design & Testing
Type Abstraction SWE Spring 2013.
Software Specifications
Programming Languages 2nd edition Tucker and Noonan
Formal Methods Lecture 16 March 22, 2011 CS 315 Spring 2011
Presentation transcript:

Specifications

Announcements HW1 is due Thursday at 1:59:59 pm

Outline Specifications Benefits of specifications Specification conventions Javadoc JML PoS specifications Specification strength Substitutability Comparing specifications

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!) conditions: constraints on values 1. From now on, I will use the term “method” which is common Java terminology, as opposed to function, the preferred nomenclature in C++.

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 A specification is an abstraction

Example Specification Precondition: len ≥ 1 && a.length = len Postcondition: result = a[0]+…+a[a.length-1] int sum(int[] a, int len) { int sum = a[0]; int i = 1; while (i < len) { sum = sum + a[i]; i = i+1; } return sum; For our purposes, we will be writing specifications that are a bit less formal than this example. Mathematical rigor is welcome, but not always necessary. Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Benefits of Specifications Precisely documents method behavior Imagine if you had to read the code of the Java libraries to figure what they do! Promotes modularity Modularity is key to the development of correct and maintainable software Specifications help organize code into small modules, with clear-cut boundaries between those modules Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Benefits of Specifications Promote modularity… Client relies on description in specification, no need to know the implementation Method must support specification, but its implementation is free otherwise! Client and method can be built simultaneously Enables reasoning about correctness “Does code do the right thing?” means “Does code conform to its specification?” Confirmed by testing and verification

So, Why Not Just Read Code? <T> boolean sub(List<T> src, List<T> part) { int part_index = 0; for (Object o : src) { if (o.equals(part.get(part_index))) { part_index++; if (part_index == part.size()) { return true; } } else { part_index = 0; return false; Can you figure this code? Spring 18 CSCI 2600, K. Kuzmin, A Milanova (example due to Michael Ernst, UW)

So, Why Not Just Read Code? Code is complicated Gives a lot more detail than client needs Understanding code is a burden Code is ambiguous What is essential and what is incidental (e.g., result of an optimization) Client needs to know what the code does, not how it does it! Spring 18 CSCI 2600, K. Kuzmin, A Milanova (based on slides by Michael Ernst, UW)

What About Comments? // method checks if part appears as // subsequence in src boolean sub(List<T> src, List<T> part) { … } Comments are important, but insufficient. They are informal and often ambiguous Specifications should be precise and concise, carrying relevant information. Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Specifications Are Concise and Precise Unfortunately, lots of code lacks specification  Programmers guess what code does by reading the code or running it This results in bugs and/or complex code with unclear behavior Specification inference is an active area of research Spring 18 CSCI 2600, K. Kuzmin, A Milanova (based on slide by Michael Ernst)

So, What’s in sub’s Specification? <T> boolean sub(List<T> src, List<T> part) { int part_index = 0; for (Object o : src) { if (o.equals(part.get(part_index))) { part_index++; if (part_index == part.size()) { return true; } } else { part_index = 0; return false; // sub returns true if part is a subsequence of src; it returns false otherwise. More needed! // src and part must be non null // If src is empty list, then false // If there is a partial match in the beginning, code will return false, even if there is a full match later. // E.g. sub <A, B, A, B, C> and part <A, B, C> will return false. These are all details client needs to know, thus, all these must be parts of the specification! Spring 18 CSCI 2600, K. Kuzmin, A Milanova (example due to Michael Ernst, UW)

So, What’s in sub’s Specification? Choice 1: // sub returns true if part is a subsequence of src; it returns false otherwise. Choice 2: // src and part should not be null // If src is the empty list, then sub returns false // If there is partial match in the beginning, sub returns false, even if there is a full match later. E.g. sub([A, B, A, B, C], [A, B, C]) is false. These are all details client needs to know, thus, all these must be parts of the specification!

What’s in sub’s Specification? This complex specification is a red flag If you end up writing a complicated specification, redesign and rewrite your code – either something is wrong or code is extremely complex and hard to reason about Rule: it is better to simplify design and code rather than try to describe complex behavior! (Michael Ernst calls this “a sneaky fringe benefit of specifications”) Spring 18 CSCI 2600, K. Kuzmin, A Milanova (based on slides by Michael Ernst)

Goal of Principles of Software One goal of Principles of Software is to instill a discipline of writing concise and precise specifications Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Javadoc Javadoc convention Method’s type signature Text description of what method does Parameters: text description of what gets passed Return: text description of what gets returned Throws: list of exceptions that may get thrown Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Example: Javadoc for String.substring public String substring(int beginIndex) Returns a new string that is a substring of this string. The substring begins with the character at the specified index and extends to the end of the string Parameters: beginIndex --- the beginning index, inclusive. Returns: the specified substring. Throws: IndexOutOfBoundsException – if beginIndex is negative or larger than the length of this String object. What are the issues with this specification? It is verbose and informal. It is not immediately clear what is expected from the client: what are the preconditions? What is guaranteed to clients: where are the postconditions? Description of parameters and returns is completely redundant. Not immediately clear from this spec that substring has NO SIDE EFFECTS. An extremely important property! As we shall see later, we often have to reason about specification strength. This verbose spec isn’t conductive for such reasoning.

PoS Specifications Specification convention due to Michael Ernst The precondition requires: clause spells out constraints on client The postcondition modifies: lists objects (typically parameters) that may be modified by the method. Any object not listed under this clause is guaranteed untouched throws: lists possible exceptions effects: describes final state of modified objects returns: describes return value Concise and precise!

Example 0 String substring(int beginIndex) requires: none modifies: none effects: none returns: new string with same value as the substring beginning at beginIndex and extending until the end of current string throws: IndexOutOfBoundsException – if beginIndex is negative or larger than the length of this String object. Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Example 1 requires: lst, old, newelt are non-null. old occurs in lst. static <T> int change(List<T> lst, T old, T newelt) requires: lst, old, newelt are non-null. old occurs in lst. modifies: lst effects: change first occurrence of old in lst with newelt. makes no other changes. returns: position of element in lst that was old and now newelt Lesson in Java static <T> int change(List<T> lst, T old, T newelt) { int i = 0; for (T curr : lst) { if (curr == old) { lst.set(i, newelt); return i; } i = i + 1; return -1; Spring 18 CSCI 2600, K. Kuzmin, A Milanova (due to Michael Ernst)

Example 2 static List<Integer> listAdd(List<Integer> lst1, List<Integer> lst2) requires: lst1, lst2 are non-null. lst1 and lst2 are same size. modifies: none effects: none returns: a new list of the same size, whose i-the element is the sum of the i-the elements of lst1 and lst2 Lesson in Java static List<Integer> listAdd(List<Integer> lst1, List<Integer> lst2) { List<Integer> res = new ArrayList<Integer>(); for (int i = 0; i < lst1.size(); i++) res.add(lst1.get(i) + lst2.get(i)); return res; } Spring 18 CSCI 2600, K. Kuzmin, A Milanova (due to Michael Ernst)

Aside: Autoboxing and Unboxing Boxed primitives. E.g., int vs. Integer Generics require reference type arguments ArrayList<Integer> al = new … Autoboxing: automatic conversion from primitive to boxed type for (int i=0; i<10; i++) al.add(i); Unboxing: automatic conversion from boxed type to primitive res.add(lst1.get(i) + lst2.get(i))

Example 3 static void listAdd2(List<Integer> lst1, List<Integer> lst2) requires: ?? modifies: ?? effects: ?? returns: ?? requires: lst1, lst2 are non-null. lst1 and lst2 are same size. modifies: lst1 effects: i-the element of lst1 is replaced with the sum of i-th elements of lst1 and lst1 returns: none static void listAdd2(List<Integer> lst1, List<Integer> lst2) { for (int i = 0; i < lst1.size(); i++) { lst1.set(i,lst1.get(i) + lst2.get(i)); } Spring 18 CSCI 2600, K. Kuzmin, A Milanova (due to Michael Ernst)

Example 4 static void uniquefy(List<Integer> lst) requires: ? modifies: ? effects: ? returns: ? Tries to remove consecutive duplicate elements in lst E.g., <1,1,2,2,3> => <1,2,3> requires: lst is nonnull, there are at most two consecutive duplicates. modifies: lst effects: removes consecutive duplicates in lst. E.g., <1,1,2,2,3> becomes <1,2,3> returns: none OR requires: lst is nonull Modifies: lst Effects: removes ceiling(n/2) duplicates static void uniquefy(List<Integer> lst) { for (int i = 0; i < lst.size()-1; i++) if (lst.get(i) == lst.get(i+1)) lst.remove(i); } Spring 18 CSCI 2600, K. Kuzmin, A Milanova (due to Michael Ernst)

Example 5 private static void swap(int[] a, int i, int j) requires: ? modifies: ? effects: ? returns: ? requires: a non-null, 0 <= i,j < a.len modifies: a effects: swaps i-th and j-th element of a returns: none OR requires: throws: NullPointerException, ArrayOutOfBoundsException static void swap(int[] a, int i, int j) { int tmp = a[j]; a[j] = a[i]; a[i] = tmp; } Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Example 6 private static void selection(int[] a) requires: ? modifies: ? effects: ? returns: ? requires: a non-nul modifies: a effects: a is sorted, a[i]<=a[i+1], for all 0 <= i < a.length-1 returns: none static void selection(int[] a) { for (int i = 0; i < a.length; i++) { int min = i; for (int j = i+1; j < a.length; j++) if (a[j] < a[min]) min = j; swap(a, i, min); } Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Javadoc for java.util.binarysearch public static int binarySearch(int[] a,int key) Searches the specified array of ints for the specified value using the binary search algorithm. The array must be sorted (as by the sort method, above) prior to making this call. If it is not sorted, the results are undefined. If the array contains multiple elements with the specified value, there is no guarantee which one will be found. Parameters: a - the array to be searched. key - the value to be searched for. Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Javadoc for java.util.binarysearch Returns: index of the search key, if it is contained in the array; otherwise, (-(insertion point) - 1). The insertion point is defined as the point at which the key would be inserted into the array; the index of the first element greater than the key, or a.length if all elements in the array are less than the specified key. Note that this guarantees that the return value will be >= 0 if and only if the key is found. So, what is wrong with this spec? Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Better binarySearch Specification public static int binarySearch(int[] a,int key) Precondition: requires: a is sorted in ascending order Postcondition: modifies: none effects: returns: i such that a[i] = key if such an i exists a negative value otherwise

Shall We Check requires Clause? If client (i.e., caller) fails to provide the preconditions, method can do anything – throw an exception or pass bad value back It is polite to check Checking preconditions Makes an implementation more robust Provides feedback to the client Avoids silent errors RULE: When the program fails, it is a lot better to fail early and informatively, then continue execution and fail later inexplicably. Spring 18 CSCI 2600, K. Kuzmin, A Milanova (based on slides by Michael Ernst)

Rule If private method, may not check If public method, do check, unless such a check is expensive E.g., requires: lst is non-null. Check E.g., requires: lst contains positive integers. Don’t check Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Shall We Check requires Clause? Example 1: requires: lst, old, newelt are non-null. old occurs in lst. Check? Example 2: requires: lst1, lst2 are non-null. lst1 and lst2 are same size. Check? binarySearch: requires: a is sorted. Check? Spring 18 CSCI 2600, K. Kuzmin, A Milanova

The JML Convention Javadocs and PoS specifications are not “machine-readable” JML (Java Modeling Language) is a formal specification language Builds on the ideas of Hoare logic End goal is automatic verification Does implementation obey contract? Given a spec S and implementation I, does I conform to S? Does client obey contract? Does it meet preconditions? Does it expect what method provides? Neither is machine-checkable.

The JML Spec for binarySearch Precondition: requires: a != null && (\forall int i; 0 < i && i < a.length; a[i-1] <= a[i]; Postcondition: ensures: // complex statement… The Verifying compiler!

Dafny Spec for binarySearch method BinarySearch(a: array<int>, key: int) returns (index: int) requires a != null && sorted(a); ensures 0 <= index ==> index < a.Length && a[index] == key; ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != key; Difficult problem and an active research area. Look up Sir Tony Hoare’s Grand Challenge

PoS Specifications PoS specifications, due to Michael Ernst, are readable and rigorous Readability ensures that the spec is a helpful abstraction Rigor facilitates reasoning Apply reasoning to prove correctness Compare specifications (more on this later) Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Aside: Specifications and Dynamic Languages In statically-typed languages (C/C++, Java) type signature is a form of specification: List<Integer> lstAdd(List<Integer> l1, List<Integer> l2) In dynamically-typed languages (Python, JavaScript), there is no type signature! def lstAdd(l1,l2): i = 0 res = [] for j in l1: res.append(j+l2[i]); i=i+1 return res Very difficult to figure what’s going on.

Aside: Specifications and Dynamic Languages Specifications are imperative. Even more so for dynamically-typed languages! Why? def add(l1,l2): i = 0 res = [] for j in l1: res.append(j+l2[i]); i=i+1 return res Start spec with type signature. Then fill in the rest of the clauses. Write spec before code! Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Specification for addLists List<Number> lstAdd(List<Number> l1, List<Number> l2) requires: ? modifies: ? effects: ? returns: ? Another possible signature and spec: List<T> add(Seq<T>, Seq<T>), where T supports +. Rule: write the spec that best matches your intention when when you write the code. My intention was to have two lists of integers and add them into a new result list. def lstAdd(l1, l2): i = 0 res = [] for j in l1: res.append(j+l2[i]); i=i+1 return res } Spring 18 CSCI 2600, K. Kuzmin, 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 is not great either Spring 18 CSCI 2600, K. Kuzmin, A Milanova (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 implementation (e.g., is input sorted?); may hinder efficiency Spring 18 CSCI 2600, K. Kuzmin, A Milanova (slide based on slides by Michael Ernst)

Outline Specifications Benefits of specifications Specification conventions Javadoc JML PoS specifications Specification strength Substitutability Comparing specifications

Specification Strength Sometimes, we need to compare specifications (we’ll see why a little later) “A is stronger than B” (i.e. A => 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” A weaker specification is easier to satisfy! And thus implement… A stronger specification is easier to use by clients.

Which One is Stronger? int find(int[] a, int value) { for (int i=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: returns: i such that a[i] = value Can you give an example of an implementation that satisfies B but not A? find satisfies both. A is stronger! A is more specific, in this case promises more in its postcondition. But we can write another implementation: int find2(a, value) { for (int i=a.length-1; i>-1; i--) if (a[i] == value) return i++; return -1; } find2 satisfies B but it it does not satisfy A. Spring 18 CSCI 2600, K. Kuzmin, A Milanova (example modified from Michael Ernst)

Which One is Stronger? Specification A: Specification B: int find(int[] a, int value) { for (int i=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 find satisfies both spec A and spec B. Which one is STRONGER? Spec B. If implementation I satisfies Spec B, then it will satisfy Spec A as well. find is such an implementation. The reverse does not hold. E.g., we can change find to return 99 if value not found. Find would still satisfy Spec A, but not Spec B! Spring 18 CSCI 2600, K. Kuzmin, 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 throws: IndexOutOfBoundsException --- if beginIndex is negative or > length of this String object Specification B. A is weaker because it requires more. It also promises less.

Why Care About Specification Strength? Because of substitutability! Principle of substitutability A stronger specification can always be substituted for a weaker one I.e., an implementation that conforms to a stronger specification can be used in a client that expects a weaker specification Spring 18 CSCI 2600, K. Kuzmin, A Milanova

Substitutability Substitutability ensures correct hierarchies Client code: X x; … x.foo(index); Client is “polymorphic”: written against X, but it is expected to work with any subclass of X A subclass of X, say Y, may have its own implementation of foo, Y.foo(int). Client must work correctly with Y.foo(int)too! If the spec of Y.foo(int) is stronger than the spec of X.foo(int) then we can safely substitute Y.foo(int) for X.foo(int)!

Client has contract with X: Substitutability Client has contract with X: X x = … // meets precondition y = x.foo(0); // expects non-zero: z = w/y; Class X requires: index >= 0 ensures: result > 0 int foo(int index) It is all about abstraction and modularity! What would be a stronger spec for Y.foo? Any condition that is weaker than index >= 0 will be fine as far as the precondition is concerned. Any condition that is stronger than X.foo’s postcondition will be fine! Class Y requires: index > 0 ensures: result >= 0 int foo(int index) BAD! Y surprises the client! The principle of substitutability tells us that if the specification of Y.foo is stronger than the specification of X.foo, then it will be ok to use Y.foo!

Strengthening and Weakening Specification Strengthen a specification Require less of client: fewer/weaker conditions in requires clause AND/OR Promise more to client: throws, effects, returns Weaken a specification Require more of client: more/stronger conditions to requires AND/OR Promise less to client: throws, effects, returns clauses are weaker, easier to write into code

Ease of Use by Client vs. Ease of Implementation A stronger specification is easier to use Client has fewer preconditions to meet Client gets more guarantees in postconditions But a stronger spec is harder to implement! Weaker specification is easier to implement Larger set of preconditions, relieves implementation from the burden of handling different cases Easier to guarantee less in postcondition But weaker spec is harder to use

Specification Strength Let specification A consist of precondition PA and postcondition QA Let specification B consist of precondition PB and postcondition QB A is stronger than B if (but not only if!) PB is stronger than PA (stronger specifications require less) QA is stronger than QB (stronger specifications promise more) In other words, PB => PA && QA => QB is a sufficient condition, but not necessary. (I.e., we may have A => B i.e., A stronger than B, where the above condition is not met.)

Exercise: Order by Strength Spec A: requires: a positive int argument returns: an int in [1..10] Spec B: requires: a non-negative int argument returns: an int in [2..5] Spec C: requires: true // the weakest condition Spec D: requires: an int in [1..10] returns: an int in [1..20] C => B => A => D. Spring 18 CSCI 2600, K. Kuzmin, 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; Pre: argument arg is an integer! Spec A is satisfied by 2, 3, 4, 5. Spec B is satisfied by 2, 4, 5. Spec C is satisfied by NONE Spec D is satisfied by 4 Spec E is satisfied by 5. A B C D E 1 2 3 4 5 Spring 18 CSCI 2600, K. Kuzmin, A Milanova (due to Michael Ernst)

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 satisfy the weaker spec B than the stronger spec A Consequently, it is easier to implement a weaker spec! Weaker specs require more AND/OR Weaker specs guarantee (promise) less