Assertions Prasun Dewan Comp 114 Assertions Declare some

  • Slides: 148
Download presentation
Assertions Prasun Dewan Comp 114

Assertions Prasun Dewan Comp 114

Assertions • Declare some property of the program • Potentially useful for – specification

Assertions • Declare some property of the program • Potentially useful for – specification – testing – formal correctness – documentation

Compile time vs. runtime properties • Some assertions language supported – Compile time •

Compile time vs. runtime properties • Some assertions language supported – Compile time • String s = next. Element() – Runtime • ((String) next. Element()) – Asserting type properties of object. – Assertions describe runtime properties

Application-independent vs. dependent • Language can provide us with fixed number of application-independent assertions.

Application-independent vs. dependent • Language can provide us with fixed number of application-independent assertions. • Cannot handle – First character of String is a letter. – Letter concept not burnt into language. • Class Character defines it – Innumerable assertions about letters possible • Second elements of string is letter. • Third element of string is letter. • Need mechanism to express arbitrary assertions

Assertions vs. Exceptions • Wrong assertion results in exception. • Wrong class cast leads

Assertions vs. Exceptions • Wrong assertion results in exception. • Wrong class cast leads to class cast exception.

Reasons for exceptions • User error – Programmer cannot prevent it • Internal error

Reasons for exceptions • User error – Programmer cannot prevent it • Internal error – Programmer can prevent • Assertions catch internal errors.

Reasons for assertions • Why catch internal errors via assertions? • Alternative: Make test

Reasons for assertions • Why catch internal errors via assertions? • Alternative: Make test runs and look at output.

Finite test runs • Some errors not exhibited in test runs. – Inconsistent string

Finite test runs • Some errors not exhibited in test runs. – Inconsistent string not printed because of user option.

Late detection • Output produced much after the cause – Storing an inconsistent string

Late detection • Output produced much after the cause – Storing an inconsistent string causes erroneous output when the string is matched not when it is stored.

Complex output • May not know what the output is, but know the relationship

Complex output • May not know what the output is, but know the relationship between input and output – (123. 345 * 789. 123 ) / 123. 345 == 789. 123 – Number is divisible by a prime factor

No manifestation in output • Some errors have to do with efficiency. – Storing

No manifestation in output • Some errors have to do with efficiency. – Storing duplicate items in a set. • Not exhibited in output

Example Assertion { y = 10/x; z = 5} assert (y == 10/x) &

Example Assertion { y = 10/x; z = 5} assert (y == 10/x) & (z == 5) Our own mathematical syntax to be mapped to Java later

Definition • Example { y = 10/x; z = 5} assert (y == 10/x)

Definition • Example { y = 10/x; z = 5} assert (y == 10/x) & (z == 5) • Statement regarding – State of program (variable values) – Program counter (currently executing statement) • PC implicit by putting assertion next to a statement – Specifies Boolean expression involving selected program variables – Assertion fails if boolean expression false – Not all program variables named • X unnamed above • Does not care about unnamed variables

Role of Assertions • Debugging – Exception thrown if assertion fails • Documentation //

Role of Assertions • Debugging – Exception thrown if assertion fails • Documentation // detailed prime factor computation code …. assert (number % prime) == 0 • Specification – Assertion defined desired result of the code to be implemented • Formal correctness – Can prove if assertion met by code. – Need assertions regarding language constructs

Recording Variables {X = X + 1} assert ? ? ? • Cannot say:

Recording Variables {X = X + 1} assert ? ? ? • Cannot say: {X = X + 1} assert X == X + 1; • Introduce recording variable {old. X = X; X = X + 1} assert X = old. X + 1 • Special variables needed to make assertions sometimes

Preconditions and Postconditions • Precondition assert (x !=0) { y = 10/x; z =

Preconditions and Postconditions • Precondition assert (x !=0) { y = 10/x; z = 5} assert (y == 10/x) & (z == 5) – What is expected before statement(block) execution • Postcondition – What is guaranteed after statement(block) if precondition met • Together define a contract

Alternative syntax • Both conditions placed before statement block. pre (x !=0) post (y

Alternative syntax • Both conditions placed before statement block. pre (x !=0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5}

Incorrect precondition? x = 0; pre (x !=0) post (y == 10/x) & (z

Incorrect precondition? x = 0; pre (x !=0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5} • Precondition may not be satisfied by previous incorrect statement. • Yet it is a correct precondition

Alternative precondition • Some assertions imply others – x > 0 x !=0 pre

Alternative precondition • Some assertions imply others – x > 0 x !=0 pre (x > 0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5} • Implied assertion is considered weaker. • Can always replace precondition with a stronger one. • Prefer weakest precondition – Requires fewest assumptions. – Statement can be used in more contexts – Better documentation

Alternative postcondition • Some assertions imply others – y == 10/x & (z ==

Alternative postcondition • Some assertions imply others – y == 10/x & (z == 5) => z == 5 pre (x != 0) post (z == 5) { y = 10/x; z = 5} • Can always replace postcondition with a weaker one • Prefer strongest postcondition – More detailed documentation – Can be used in more contexts • Can be followed by statements with stronger preconditions.

Too strong Comp 114 • pre arrays, loops, procedures • {Take Comp 114} •

Too strong Comp 114 • pre arrays, loops, procedures • {Take Comp 114} • post objects, inheritance, trees, recursion, assertions, composite, iterator, visitor pattern • pre arrays, loops, procedures, objects, inheritance • {Take Comp 114} • post recursion Too weak

Course Analogy • Preconditions – Declared course prerequisite • Post conditions – Advertised objectives

Course Analogy • Preconditions – Declared course prerequisite • Post conditions – Advertised objectives • Stronger precondition – Does not allow some students to enroll • Weaker post conditions – Does not allow enrollment in future courses

Strongest Postcondition? • Says nothing about x. pre (x !=0) post (y == 10/x)

Strongest Postcondition? • Says nothing about x. pre (x !=0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5}

Strongest Postcondition • Strongest post condition given pre (x !=0) the precondition post (y

Strongest Postcondition • Strongest post condition given pre (x !=0) the precondition post (y == 10/x) & (z == 5) & (x != 0) • The stronger the pre condition, { y = 10/x; z = 5} stronger the post condition.

Alternative weakest/strongest pair Stronger precondition pre (x > 0) post (y == 10/x) &

Alternative weakest/strongest pair Stronger precondition pre (x > 0) post (y == 10/x) & (z == 5) & (x > 0) & (y > 0) { y = 10/x; z = 5} Stronger postcondition

Multiple valid pairs • Weakest precondition relative to post condition. • Strongest post condition

Multiple valid pairs • Weakest precondition relative to post condition. • Strongest post condition relative to pre condition. • A statement not associated with a unique pair that is best. • Strengthening the precondition strengthens the post condition • What is the “right pair? ”

Two approaches • Start with a precondition – Find the strongest postcondition we can

Two approaches • Start with a precondition – Find the strongest postcondition we can prove. • Start with a post condition – Find the weakest precondtion for it.

Theoretical specification point of view • Specify the result needed as a post condition.

Theoretical specification point of view • Specify the result needed as a post condition. • Identify the weakest precondition needed to obtain the result. • Write a program that satisfies the pair.

Reality specification point of view • Based on what you can assume you change

Reality specification point of view • Based on what you can assume you change your expectations. • Iterative process.

Debugging/specification/ documentation point of view • Precondition of a statement should be weakest one

Debugging/specification/ documentation point of view • Precondition of a statement should be weakest one necessary for “correct” operation of program. – Correct means no exception. • A statement that is not equivalent should not have the same pre and post condition

Debugging/specification/ documentation point of view pre (x >0) post (y == 10/x) & (z

Debugging/specification/ documentation point of view pre (x >0) post (y == 10/x) & (z == 5) & (x > 0) { y = 10/x; z = 5} pre (x >0) post (y == 10/x) & (z == 5) & (x > 0) { y = 10/x; z = 5; x = abs(x) + 1} Statements are not equivalent

Debugging/ specification/ documentation point of view Best pre and post conditions pre (x !=0)

Debugging/ specification/ documentation point of view Best pre and post conditions pre (x !=0) post (y == 10/x) & (z == 5) & (x != 0) { y = 10/x; z = 5}

Proving programs correct point of view • Precondition can be stronger than one that

Proving programs correct point of view • Precondition can be stronger than one that is the best one for the statement from debugging/specification/documentation point of view • Allows us to derive pre and post conditions of containing statement/program

Program correctness proof pre post (x == 1) {x = 1} pre (x ==

Program correctness proof pre post (x == 1) {x = 1} pre (x == 1) post (y == 10/x) & (z == 5) & (x == 1) { y = 10/x; z = 5}

Program correctness proof pre post (y == 10/x) & (z == 5) & (x

Program correctness proof pre post (y == 10/x) & (z == 5) & (x == 1) {x = 1; y = 10/x; x= 5}

Changeable assertions • What we assert about a statement (to prove program correct) may

Changeable assertions • What we assert about a statement (to prove program correct) may depend on what is executed before it. • Need facilities to change assertions easily. • Proxies explained later address this.

Weakest possible condition • • • Implied by anything true p true If p

Weakest possible condition • • • Implied by anything true p true If p is true then true is true. But true is always true. So p can be any boolean expression.

Strongest possible condition • • Implies anything false p If false is true then

Strongest possible condition • • Implies anything false p If false is true then p is true But false is never true. So any p is implied. “I will give you a million dollars when hell freezes over”

Important equivalence • P Q !P | Q • P true !P | true

Important equivalence • P Q !P | Q • P true !P | true • false Q !false | Q true

Asserting false switch c { case ‘a’: … case ‘b’: … default: assert false

Asserting false switch c { case ‘a’: … case ‘b’: … default: assert false } Unreachable statement

Invariant • True before and after statement pre (x !=0) post (y == 10/x)

Invariant • True before and after statement pre (x !=0) post (y == 10/x) & (z == 5) & (x != 0) { y = 10/x; z = 5}

Separately declared • List invariant separately inv (x !=0) post (y == 10/x) &

Separately declared • List invariant separately inv (x !=0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5}

Invariants for debugging purposes • Should never be false – False strongest invariant of

Invariants for debugging purposes • Should never be false – False strongest invariant of all statements. – But not best for a reachable statement as it does not convey useful information – Never assert it for reachable statements if assertion not done for program proofs. • Should never involve recording variables – recording variables describe how program variables change – invariants describe how these variables do not change

Loop Invariant sum = 0; j = 0; while (j < n) { j++;

Loop Invariant sum = 0; j = 0; while (j < n) { j++; sum = sum + j; } • Holds true before and after each loop iteration, that is, before and after each execution of loop body.

Loop Invariant • Holds true before and after each loop inv (sum = 0

Loop Invariant • Holds true before and after each loop inv (sum = 0 j k) & (j <= n ) & (j >= 0) iteration, that is, sum = 0; before and after each j = 0; execution of loop while (j < n) { body. j++; sum = sum + j; }

Method assertions invariant x != 0 post (y == 10/x) & (z == 5)

Method assertions invariant x != 0 post (y == 10/x) & (z == 5) & (x != 0) void m () { y = 10/x; z = 5; } • Preconditions, postconditions, invariants associated with method body

Class assertions public class C { int x =0; int y = 1; public

Class assertions public class C { int x =0; int y = 1; public void increment. XAnd. Y () { increment. X(); increment. Y(); } public int get. X() { return x; } public int get. Y() { return y; } increment. X() { x++; } increment. Y() { y++; } } • Preconditions, postconditions, invariants shared by all public methods of class

Class assertions inv y == x + 1 public class C { int x

Class assertions inv y == x + 1 public class C { int x =0; int y = 1; public void increment. XAnd. Y () { increment. X(); increment. Y(); } public int get. X() { return x; } public int get. Y() { return y; } increment. X() { x++; } increment. Y() { y++; } } • Preconditions, postconditions, invariants shared by all public methods of class

Expressing Assertions • Natural language – All array elements are not odd. – All

Expressing Assertions • Natural language – All array elements are not odd. – All array elements are either odd or positive. – Easy to read but ambiguous. • Programming language – Library or language constructs – Executable, unambiguous but language-dependent and awkward • Useful for debugging • Specification cannot be done before language decided. • Mathematical language – Uambiguous, time tested, convenient but not executable

Propositional Calculus • Logic operators • not, and, or • We will use Java

Propositional Calculus • Logic operators • not, and, or • We will use Java syntax. • Quantifiers – Universal ( ) – Existential ( ) • Propositional variables • Program • Others: Recording, Quantifier • Propositions – Boolean expressions involving operators, variables, and quantifiers • Simple/quantified propositions – Do not use/use quantifiers

Propositional Algebra • Calculus based on algebra • Algebra defines – Arithmetic operations –

Propositional Algebra • Calculus based on algebra • Algebra defines – Arithmetic operations – Relations operations – We will use Java syntax

Example Propositions • Simple propositions – – True False X>6 (X > 6 )

Example Propositions • Simple propositions – – True False X>6 (X > 6 ) & (Y < 2) • Quantified – j: 0 <= j < b. size() : b. element. At(j) != null • All elements of B are not null – j: 0 <= j < b. size(): b. element. At(j) != null • At least one element of B is not null.

Quantified Propositions • Quantified – j: 0 <= j < b. size(): b. element.

Quantified Propositions • Quantified – j: 0 <= j < b. size(): b. element. At(j) != null • General form: – Qx: D(x): P(x) – Q is either or quantifier – X is quantified variable – D(x) is domain description – P(x) is sub-proposition • Sub-proposition – Simple or quantified proposition in terms of quantifier • Domain – A collection of values used in sub-proposition evaluation – b. element. At(0), … b. element. At(B. size() – 1 • Domain description – Describes domain using quantified variable

Expressing Assertions in Java • Write your own code. • Libraries • Language support

Expressing Assertions in Java • Write your own code. • Libraries • Language support – Does not support quantifiers – Works for 1. 4 – You have 1. 3

Assertion Failed Exception package assertions; public class An. Assertion. Failed. Exception extends Runtime. Exception

Assertion Failed Exception package assertions; public class An. Assertion. Failed. Exception extends Runtime. Exception { public An. Assertion. Failed. Exception () {}; public An. Assertion. Failed. Exception (String init. Value) { super (init. Value); } } • Thrown when assertion fails • Unchecked because internal error • Can subclass it for specific assertions • Will use message in examples

Assert methods package assertions; import java. util. Enumeration; public class An. Asserter { public

Assert methods package assertions; import java. util. Enumeration; public class An. Asserter { public static void assert (boolean proposition, String message) throws An. Assertion. Failed. Exception { if (!proposition) throw new An. Assertion. Failed. Exception (message); } public static void assert (boolean proposition) throws An. Assertion. Failed. Exception { assert (proposition, “”); } • Used for simple assertions }

Using assert //inv (sum = 0 j k) & (j <= n ) &

Using assert //inv (sum = 0 j k) & (j <= n ) & (j >= 0) sum = 0; j = 0; while (j < n) { j++; sum = sum + j; } • Must write our boolean expression that is passed to assert – public static int sum (int from, int to) { … } • Must code pre/post conditions and invariants as assert calls

Using assert sum = 0; j = 0; //inv (sum = 0 j k)

Using assert sum = 0; j = 0; //inv (sum = 0 j k) & (j <= n ) & (j >= 0) while (j < n) { An. Asserter. assert (j <= n && j >= 0 && sum == sum(0, j)) j++; sum = sum + j; An. Asserter. assert (j <= n && j > =0 && sum == sum(0, j)) } • Must write our boolean expression that is passed to assert – public static int sum (int from, int to) { … } • Must code pre/post conditions and invariants as assert calls

Class and Method Invariants //inv y = x + 1 • Class invariant public

Class and Method Invariants //inv y = x + 1 • Class invariant public class C { – Encode them as invariants of int x =0; all public methods. int y = 1; public void increment. XAnd. Y () { • Method invariant increment. X(); – Put assert at start and end of increment. Y(); public methods } public int get. X() { return x; } public int get. Y() { return y; } increment. X() { x++; } increment. Y() { y++; } }

Class and Method Invariants //inv y = x + 1 public class C {

Class and Method Invariants //inv y = x + 1 public class C { int x =0; int y = 1; void assert. Class. Invariant{ An. Asserter. assert (y == x + 1); } public void increment. XAnd. Y () { assert. Class. Invariant(); increment. X(); increment. Y(); assert. Class. Invariant(); } public int get. X() { assert. Class. Invariant(); ? ? ? return x; } … } • Class invariant – Encode them as invariants of all public methods. • Method invariant – Put assert at start and end of method Cannot put something after return and return may have side effects (return x++)

Class and Method Invariants //inv y = x + 1 public class C {

Class and Method Invariants //inv y = x + 1 public class C { int x =0; int y = 1; void assert. Class. Invariant{ An. Asserter. assert (y == x + 1); } void internal. Increment. XAnd. Y () { increment. X(); increment. Y(); } public void increment. XAnd. Y () { assert. Class. Invariant(); internal. Increment. XAnd. Y(); assert. Class. Invariant(); } internal. Get. X() { return x; } public int get. X() { assert. Class. Invariant(); int ret. Val = internal. Get. X(); assert. Class. Invariant(); return ret. Val; } • Can define another proxy method that asserts and calls the real method – Keeps asserting code separate – Useful for functions – Useful when multiple exit points Asserting proxy method

Multiple exit points char assign. Grade (int score) { if (score >= 50) {

Multiple exit points char assign. Grade (int score) { if (score >= 50) { grade = ‘P’; return; } else grade = ‘F’; } char asserting. To. Grade (int score) { assign. Grade(score); assert (grade == ‘F’ || grade == ‘P’); } • Can define another proxy method that asserts and calls the real method – Keeps asserting code separate – Useful for functions – Useful when multiple exit points

Quantified Assertions • Syntax – Qx: D(x): P(x) – j: 0 <= j <

Quantified Assertions • Syntax – Qx: D(x): P(x) – j: 0 <= j < b. size(): b. element. At(j) != null • Goal: – Write general boolean functions that take as arguments encoding of the elements of domain and return true iff proposition is true – Will write separate functions for universal and existential quantifer

Goal package assertions; import java. util. Enumeration; public class AQuantifier { public static boolean

Goal package assertions; import java. util. Enumeration; public class AQuantifier { public static boolean for. All (…) { … } public static boolean there. Exists (…) { … } } • Need to fill the …

Problem with inaccessible variables • Syntax – Qx: D(x): P(x) – j: 0 <=

Problem with inaccessible variables • Syntax – Qx: D(x): P(x) – j: 0 <= j < b. size(): b. element. At(j) != null • How to describe D(x) and P(x)? – Cannot pass expression string as variables involved have no meaning to library – Will pass one argument describing the domain • Collection of elements – Another argument describing the subproposition to be evaluated for each domain element.

How to describe domain? • Syntax – Qx: D(x): P(x) – j: 0 <=

How to describe domain? • Syntax – Qx: D(x): P(x) – j: 0 <= j < b. size(): b. element. At(j) != null • Domain can be – Array, Vector, String. History, … • Need a common interface to describe elements – java. util. Enumeration

Describing the domain package assertions; import java. util. Enumeration; public class AQuantifier { public

Describing the domain package assertions; import java. util. Enumeration; public class AQuantifier { public static boolean for. All ((Enumeration domain, …) { while (domain. has. More. Elements()) … } public static boolean there. Exists ((Enumeration domain, …) { while (domain. has. More. Elements()) … } } An. Asserter. assert(AQuantifier. for. All(B. elements(), …, "Some element of B is null"); An. Asserter. assert(AQuantifier. there. Exists(b. elements(), …, "All elements of B are null"); Need to fill …

How to describe Subproposition • Syntax – Qx: D(x): P(x) – j: 0 <=

How to describe Subproposition • Syntax – Qx: D(x): P(x) – j: 0 <= j < b. size(): b. element. At(j) != null • Cannot pass expression string as variables involved have no meaning to library • But can pass function that evaluates it. – boolean is. Not. Null(Object element) { return element != null; } • Function will be evaluated for each domain element by our libraries

Subproposition as a function package assertions; import java. util. Enumeration; public class AQuantifier {

Subproposition as a function package assertions; import java. util. Enumeration; public class AQuantifier { public static boolean for. All (Enumeration domain, (object boolean) sub. Proposition) { while (domain. has. More. Elements()) if (!sub. Proposition (domain. next. Element()) return false; return true; } public static boolean there. Exists ((Enumeration domain, (object boolean) sub. Proposition) { while (domain. has. More. Elements()) if (!sub. Proposition (domain. next. Element()) return true; return false; } } An. Asserter. assert(AQuantifier. for. All(B. elements(), is. Not. Null), "Some element of B is null"); An. Asserter. assert(AQuantifier. there. Exists(b. elements(), is. Not. Null), "All elements of B are null");

How to describe Subproposition package assertions; public interface Element. Checker { public boolean visit

How to describe Subproposition package assertions; public interface Element. Checker { public boolean visit (Object element); } • Cannot pass expression string. • But can pass function that evaluates it. – boolean is. Not. Null(Object element) { return element != null; } package visitors; • import assertions. Element. Checker; public class ANon. Null. Checker • implements Element. Checker { public boolean visit(Object element) { return (element != null); • } } Java does not support function parameters But allows object parameters – Object = data + functions All subproposition objects implement same interface • A subproposition object visits each element

Describing the subproposition package assertions; Call import java. util. Enumeration; public class AQuantifier {

Describing the subproposition package assertions; Call import java. util. Enumeration; public class AQuantifier { public static boolean for. All (Enumeration domain, Element. Checker sub. Proposition) { Callback while (domain. has. More. Elements()) if (!sub. Proposition. visit(domain. next. Element())) return false; return true; } public static boolean there. Exists (Enumeration domain, Element. Checker sub. Proposition) { while (domain. has. More. Elements()) if (sub. Proposition. visit(domain. next. Element())) return true; return false; } } An. Asserter. assert(AQuantifier. for. All(b. elements(), new ANon. Null. Checker()), "Some element of B is null"); An. Asserter. assert(AQuantifier. there. Exists(b. elements(), new ANon. Null. Checker()), "All elements of B are null");

Calls vs. Callbacks • Calls – calls from reusing class to reused class •

Calls vs. Callbacks • Calls – calls from reusing class to reused class • Callbacks – calls from reused class to reusing class. – not to implement a symbiotic relationship – done to service calls

Subproposition accessing vars other than domain elements • • j: 0 <= j <

Subproposition accessing vars other than domain elements • • j: 0 <= j < b. size(): b. element. At(j) != a. element. At(0) package visitors; import assertions. Element. Checker; public class ANon. Null. Checker implements Element. Checker { public boolean visit(Object element) { return (element != null); } } No constructor An. Asserter. assert(AQuantifier. for. All(b. elements(), new ANon. Null. Checker()), "Some element of B is null");

Subproposition accessing vars other than domain elements • • j: 0 <= j <

Subproposition accessing vars other than domain elements • • j: 0 <= j < b. size(): b. element. At(j) != a. element. At(0) Each external var becomes constructor parameter package visitors; import assertions. Element. Checker; public class An. Inequality. Checker implements Element. Checker { Object test. Object; public An. Inequality. Checker(Object the. Test. Object) { test. Object = the. Test. Object; } public boolean visit(Object element) { return !element. equals(test. Object); } } An. Asserter. assert(AQuantifier. for. All(b. elements(), new An. Inequality. Checker(a. element. At(0))), "Some element of b is equal to a. element. At(0)");

Visitor Pattern • • Some collection C of elements of type T Visitor interface

Visitor Pattern • • Some collection C of elements of type T Visitor interface – public interface Element. Checker { public boolean visit (Object element); } – public interface V {public T 2 m (T p); } • One or more traverser methods that use collection and visitor interface to pass one or more collection elements to the method. – public static boolean for. All (Enumeration domain, Element. Checker sub. Proposition) {…sub. Proposition. visit(domain. next. Element()); – traverser 1 (C c, V v) { …v. m(element of C)…} • Implementation of interface whose constructors take as arguments external variables that need to be accessed by the visitor method public class An. Inequality. Checker implements Element. Checker { Object test. Object; public An. Inequality. Checker(Object the. Test. Object) {…} public boolean visit(Object element) {…}; } public class AV 1 implements V { public AV 1 (T 1 p 1, … Tn p. N) { …} public T 2 m (T p) { … } } • Client passes traverser visitor implementation and collection – AQuantifier. for. All(b. elements(), new An. Inequality. Checker(a. element. At(0))); – traverser 1(c, new AV 1(a 1, . . a. N));

Visitor Pattern Collection Interface C with elements of type T component element 1: T

Visitor Pattern Collection Interface C with elements of type T component element 1: T uses Traverser 1 element 1: T Traverser 2 Visitor Interface implements Visitor Class 1 Visitor Class 2

Example of Visitor Pattern Enumeration uses component Object for. All() Object there. Exists() Element.

Example of Visitor Pattern Enumeration uses component Object for. All() Object there. Exists() Element. Checker implements ANon. Null Checker An. Inequality Checker

Nested Assertions j: 0 <= j < b. size(): k: 0 <= k <

Nested Assertions j: 0 <= j < b. size(): k: 0 <= k < b. element. At(j). size(): b. element. At(j). element. At(k) != null package visitors; import assertions. Element. Checker; public class ANon. Null. Checker implements Element. Checker { public boolean visit(Object element) { return (element != null); } } package visitors; import assertions. Element. Checker; public class AFor. All. Checker implements Element. Checker { public boolean visit(Object element) { Enumeration children = ( (Vector) element). elements(); return AQuantifier. for. All(children, new ANon. Null. Checker())); Visiting Hierarchical Structures (Trees) } } An. Asserter. assert(AQuantifier. for. All(b. elements(), new AFor. All. Checker(), "Some leaf-level element of b is null”);

Example of Pattern in Everyday Applications • • • Program tree A visitor for

Example of Pattern in Everyday Applications • • • Program tree A visitor for printing all nodes. Another for type checking. Yet another for generating code Do not want to put all of this code in tree class. • In any case, printing should not be in tree.

Java 1. 4 Assertion Support • Assertion. Error exception = An. Assertion. Failed. Exception

Java 1. 4 Assertion Support • Assertion. Error exception = An. Assertion. Failed. Exception • assert <boolean expression> = An. Asserter. assert(<boolean expression>, “”); • assert <boolean expression>: <value> = An. Asserter. assert(<boolean expression>, string representation of <value> • Compile option determine if assert is keyword – javac –source 1. 4 models/ACounter. java • Assertions can be dynamically turned on or off for package or Class – java –da: bus. uigen –ea models. ACounter • No support for quantifiers.

Error vs. Exception • Java assertion failure results in Assertion. Error • Subclass of

Error vs. Exception • Java assertion failure results in Assertion. Error • Subclass of Error rather than Run. Time. Exception • Reasoning: – Convention dictates that Run. Time. Exception should be caught – Should “discourage programmers from attempting to recover from assertion failures. ” • Might do custom reporting, mail error report etc. – Decision was controversial

Modularizing assertion code • How to not clutter regular with assertion code. • How

Modularizing assertion code • How to not clutter regular with assertion code. • How to turn off/change library-based assertion code?

Proxy Methods char assign. Grade (int score) { if (score >= 50) { grade

Proxy Methods char assign. Grade (int score) { if (score >= 50) { grade = ‘P’; return; } else grade = ‘F’; } char asserting. To. Grade (int score) { assign. Grade(score); assert (grade == ‘F’ || grade == ‘P’); } • Can define another proxy method that asserts and calls the real method – Keeps asserting code separate – Useful for functions – Useful when multiple exit points

Proxy classes • Put assertion code in special classes that are proxies for real

Proxy classes • Put assertion code in special classes that are proxies for real classes. • Factory, factory selectors and factory methods can be used to choose between proxy and regular classes.

Counter package models; public class ACounter implements Counter { int counter = 0; public

Counter package models; public class ACounter implements Counter { int counter = 0; public void add (int amount) { counter += amount; } public int get. Value() { return counter; } }

Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends

Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends ACounter { public void add (int amount) { int old. Counter = counter; super. add(amount); An. Asserter. assert(counter == old. Counter + amount, "New counter: " + counter + " != old counter: " + old. Counter + " + amount: " + amount); } }

Example of Proxy Pattern ACounter implements IS-A implements AChecked Counter

Example of Proxy Pattern ACounter implements IS-A implements AChecked Counter

Proxy Pattern Real Subject Class IS-A Proxy Class implements Subject Interface implements

Proxy Pattern Real Subject Class IS-A Proxy Class implements Subject Interface implements

Proxies in everyday apps • Proxy is a stand-in for real subject. • Adds

Proxies in everyday apps • Proxy is a stand-in for real subject. • Adds to one or more method implementations • Web proxies – Cache data – Redirect to nearest server • Proxy may – – Log Cache (remote proxy) Provide access control Assert

Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends

Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends ACounter { public void add (int amount) { int old. Counter = counter; super. add(amount); An. Asserter. assert(counter == old. Counter + amount, "New counter: " + counter + " != old counter: " + old. Counter + " + amount: " + amount); } } Alternative way of doing proxy?

Delegating Proxy • Proxy HAS-A reference to the Subject and not IS-A Subject. •

Delegating Proxy • Proxy HAS-A reference to the Subject and not IS-A Subject. • Proxy is called delegator and subject is called delegate

Delegating Proxy-based Counter package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter

Delegating Proxy-based Counter package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter implements Counter { Counter counter; public ADelegating. Checked. Counter (Counter the. Counter) { counter = the. Counter; } public void add (int amount) { int old. Val = counter. get. Value(); counter. add(amount); int new. Val = counter. get. Value(); An. Asserter. assert(new. Val == old. Val + amount, "New counter: " + new. Val + " != old counter: " + old. Val + " + amount: " + amount); } public int get. Value() { return counter. get. Value(); } }

Example of Delegating Proxy ACounter implements HAS_A AChecked Counter implements Counter

Example of Delegating Proxy ACounter implements HAS_A AChecked Counter implements Counter

Delegating Proxy Real Subject Class HAS_A Proxy Class implements Subject Interface implements

Delegating Proxy Real Subject Class HAS_A Proxy Class implements Subject Interface implements

Inheritance vs. Delegation Real Subject Class implements Subject Interface IS-A Proxy Class implements Subject

Inheritance vs. Delegation Real Subject Class implements Subject Interface IS-A Proxy Class implements Subject Interface Real Subject Class HAS-A Proxy Class implements

OMT (Object Modeling Technique) Real Subject Class implements Subject Interface IS-A Proxy Class implements

OMT (Object Modeling Technique) Real Subject Class implements Subject Interface IS-A Proxy Class implements Subject Interface Real Subject Class HAS-A Proxy Class implements

Added notation of implements Real Subject Class implements Subject Interface IS-A Proxy Class implements

Added notation of implements Real Subject Class implements Subject Interface IS-A Proxy Class implements Subject Interface Real Subject Class HAS-A Proxy Class implements

Inheritance vs. Delegation Reused Class Reused Interface Reusing Class Reusing Interface

Inheritance vs. Delegation Reused Class Reused Interface Reusing Class Reusing Interface

Inheritance vs. Delegation: Instances Reused Class Reusing Class Reused Class instance Physical component Reusing

Inheritance vs. Delegation: Instances Reused Class Reusing Class Reused Class instance Physical component Reusing Class instance

Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends

Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends ACounter { public void add (int amount) { int old. Counter = counter; super. add(amount); An. Asserter. assert(counter == old. Counter + amount, "New counter: " + counter + " != old counter: " + old. Counter + " + amount: " + amount); } }

Delegating Proxy-based Counter package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter

Delegating Proxy-based Counter package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter implements Counter { Counter counter; public ADelegating. Checked. Counter (Counter the. Counter) { counter = the. Counter; } public void add (int amount) { int old. Val = counter. get. Value(); counter. add(amount); int new. Val = counter. get. Value(); An. Asserter. assert(new. Val == old. Val + amount, "New counter: " + new. Val + " != old counter: " + old. Val + " + amount: " + amount); } public int get. Value() { return counter. get. Value()b; } }

Inheritance vs. Delegation: Init methods/Constructor Reused Class Reusing Class declares Constructor/init (…) Reused Class

Inheritance vs. Delegation: Init methods/Constructor Reused Class Reusing Class declares Constructor/init (…) Reused Class Reusing Class declares Constructor/init (delegate, …)

Inheritance vs. Delegation: Super calls Reused Class Reusing Class Reused Class declares Reused method

Inheritance vs. Delegation: Super calls Reused Class Reusing Class Reused Class declares Reused method m super. m() declares Method n declares Reused method m delegate. m() Reusing Class declares Method n

Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends

Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends ACounter { public void add (int amount) { int old. Counter = counter; super. add(amount); An. Asserter. assert(counter == old. Counter + amount, "New counter: " + counter + " != old counter: " + old. Counter + " + amount: " + amount); } }

Delegating Proxy-based Counter package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter

Delegating Proxy-based Counter package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter implements Counter { Counter counter; public ADelegating. Checked. Counter (Counter the. Counter) { init(the. Counter); } public void add (int amount) { int old. Val = counter. get. Value(); counter. add(amount); int new. Val = counter. get. Value(); An. Asserter. assert(new. Val == old. Val + amount, "New counter: " + new. Val + " != old counter: " + old. Val + " + amount: " + amount); } public int get. Value() { return counter. get. Value(); } }

Inheritance vs. Delegation: Reused Methods Reused Class declares Reused method m Delegation is more

Inheritance vs. Delegation: Reused Methods Reused Class declares Reused method m Delegation is more work! Reusing Class Reused Class declares Reused method m delegate. m() Reusing Class declares m stub

Abstract class public abstract class An. Abstract. Title. To. Course. Mapper implements Title. To.

Abstract class public abstract class An. Abstract. Title. To. Course. Mapper implements Title. To. Course. Mapper { public An. Abstract. Title. To. Course. Mapper() { fill. Courses(); } abstract Regular. Course get. Regular. Course(); abstract Freshman. Seminar get. Freshman. Seminar(); void fill. Courses() { Regular. Course intro. Prog = get. Regular. Course (); Freshman. Seminar lego. Robots = get. Freshman. Seminar(); . . . } public String get. Title() { return title. To. Course. Mapper. get. Title(); }. . . }

Concrete course user public class ATitle. To. Course. Mapper extends An. Abstract. Title. To.

Concrete course user public class ATitle. To. Course. Mapper extends An. Abstract. Title. To. Course. Mapper { Regular. Course get. Regular. Course() { return new ARegular. Course(); } Freshman. Seminar get. Freshman. Seminar() { return new AFreshman. Seminar(); } }

Delegate class public class ATitle. To. Course. Mapper. Delegate implements Title. To. Course. Mapper

Delegate class public class ATitle. To. Course. Mapper. Delegate implements Title. To. Course. Mapper { Course. Factory delegator; public ATitle. To. Course. Mapper. Delegate(Course. Factory the. Delegator) { delegator = the. Delegator; fill. Courses(); } void fill. Courses() { Regular. Course intro. Prog = delegator. get. Regular. Course (); Freshman. Seminar lego. Robots = delegator. get. Freshman. Seminar(); . . . } public String get. Title() { return title. To. Course. Mapper. get. Title(); }. . . }

Concrete course user public class ATitle. To. Course. Mapper. Delegator implements Title. To. Course.

Concrete course user public class ATitle. To. Course. Mapper. Delegator implements Title. To. Course. Mapper, Course. Factory { public Regular. Course get. Regular. Course() { return new ARegular. Course(); } public Freshman. Seminar get. Freshman. Seminar() { return new AFreshman. Seminar(); } public String get. Title() { return title. To. Course. Mapper. get. Title(); }. . . }

Inheritance vs. Delegation: Callbacks declares Reused Class Reusing Class declares Reused method m Abstract

Inheritance vs. Delegation: Callbacks declares Reused Class Reusing Class declares Reused method m Abstract or Overridden Method n this. n() Method n Reused method m delegator. n() Method n with possibly more access

Calls vs. Callbacks • Calls – calls from reusing class to reused class •

Calls vs. Callbacks • Calls – calls from reusing class to reused class • Callbacks – calls from reused class to reusing class. – not to implement a symbiotic relationship – done to service calls

Inheritance vs. Delegation: Constructors/Init methods for callbacks Reused Class declares Constructor/init (…) Reusing Class

Inheritance vs. Delegation: Constructors/Init methods for callbacks Reused Class declares Constructor/init (…) Reusing Class Reused Class Reusing Class declares Constructor/init (delegator, …)

Access problems • Occur with callbacks. • And if reusing class accesses variables of

Access problems • Occur with callbacks. • And if reusing class accesses variables of reused class

Inheriting String Database package collections; public class AString. Database extends AString. History implements String.

Inheriting String Database package collections; public class AString. Database extends AString. History implements String. Database { public void delete. Element (String element) { shift. Up(index. Of(element)); } public int index. Of (String element) { int index = 0; while ((index < size) && !element. equals(contents[index])) index++; return index; } void shift. Up (int start. Index) { int index = start. Index ; while (index + 1 < size) { contents[index] = contents[index + 1]; index++; } size--; } public boolean member(String element) { return index. Of (element) < size; } public void clear() { size = 0; }

Delegating String Set Class as type package collections; import enums. String. Enumeration; and accessing

Delegating String Set Class as type package collections; import enums. String. Enumeration; and accessing public class ADelegating. String. Database implements String. Database { non public AString. History string. History = new AString. History(); public void delete. Element (String element) { variables in shift. Up(index. Of(element)); same package } public int index. Of (String element) { int index = 0; while ((index < string. History. size) && Instantiating !element. equals(string. History. contents[index])) delegate rather than index++; return index; getting reference } from constructor. init void shift. Up (int start. Index) { int index = start. Index ; method while (index + 1 < string. History. size) { string. History. contents[index] = string. History. contents[index + 1]; index++; } string. History. size--; }

Delegating String Set public boolean member(String element) { return index. Of (element) < string.

Delegating String Set public boolean member(String element) { return index. Of (element) < string. History. size; } public void clear() { string. History. size = 0; } public int size() { return string. History. size(); } public String element. At (int index) { return string. History. element. At(index); } public String. Enumeration elements() { return string. History. elements(); } public void add. Element(String element) { string. History. add. Element(element); } } Large number of forwarding stubs

Access issues • Callbacks methods – must be given public access if interface types

Access issues • Callbacks methods – must be given public access if interface types the delegator. – can be given protected or default access – but requires class types, delegator and delegator class in same package • May need to give access to reused class variables also – through public methods – or putting delegate and delegator in same package, giving them protected/default access and using class as type

Cons of Delegation • Need to instantiate multiple classes. • Need to compose instances.

Cons of Delegation • Need to instantiate multiple classes. • Need to compose instances. • Need to define stub methods • Access problems

Pros of Delegation Reused Class Reused Interface Reusing Class Reusing Interface

Pros of Delegation Reused Class Reused Interface Reusing Class Reusing Interface

Substituting Reused Class 2 Reused Interface Reusing Class 2 Reusing Interface Reused Class 2

Substituting Reused Class 2 Reused Interface Reusing Class 2 Reusing Interface Reused Class 2 Reused Interface Reusing Class Reusing Interface

Substituting Reused Class • Another implementation of reused interface – in inheritance requires another

Substituting Reused Class • Another implementation of reused interface – in inheritance requires another implementation of reusing class that duplicates methods of original reusing class. – In delegation simply requires a different object to be passed to constructor

New Inheriting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter

New Inheriting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter 2 extends ACounter 2 { public void add (int amount) { int old. Counter = counter; super. add(amount); An. Asserter. assert(counter == old. Counter + amount, "New counter: " + counter + " != old counter: " + old. Counter + " + amount: " + amount); } }

Orginal Delegating Proxy package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter

Orginal Delegating Proxy package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter implements Counter { Counter counter; public ADelegating. Checked. Counter (Counter the. Counter) { counter = the. Counter; } public void add (int amount) { int old. Val = counter. get. Value(); counter. add(amount); int new. Val = counter. get. Value(); An. Asserter. assert(new. Val == old. Val + amount, "New counter: " + new. Val + " != old counter: " + old. Val + " + amount: " + amount); } public int get. Value() { return counter. get. Value(); } }

Multiple Reusing Classes • Inheritance Reused Class Reusing Class 1 Reusing Class 2 –

Multiple Reusing Classes • Inheritance Reused Class Reusing Class 1 Reusing Class 2 – each possible combination of reusing classes bound at compile time – Duplicates code • Delegation – can be changed dynamically

Delegation-based MVC AChecked. Counter ACounter. Console View ACounter. Controller ACounter. JOption View AConsole. Controller.

Delegation-based MVC AChecked. Counter ACounter. Console View ACounter. Controller ACounter. JOption View AConsole. Controller. And. View. And. JOption. View

Inheritance-based MVC ACounter. With. Console. View ACounter. With. Console. And. JOption. View. And. Controller

Inheritance-based MVC ACounter. With. Console. View ACounter. With. Console. And. JOption. View. And. Controller No facades or notification needed

Controller with Console View package views; import models. ACounter; public class ACounter. With. Console.

Controller with Console View package views; import models. ACounter; public class ACounter. With. Console. View extends ACounter { void append. To. Console(int counter. Value) { System. out. println("Counter: " + counter. Value); } public void add (int amount) { super. add(amount); append. To. Console(get. Value()); } }

Controller with Console and JOption View package views; import models. ACounter; import javax. swing.

Controller with Console and JOption View package views; import models. ACounter; import javax. swing. JOption. Pane; public class ACounter. With. Console. And. JOption. View extends ACounter. With. Console. View { void display. Message(int counter. Value) { JOption. Pane. show. Message. Dialog(null, "Counter: " + counter. Value); } public void add (int amount) { super. add(amount); display. Message(get. Value()); } }

Controller with Console and JOption View and Controller package controllers; import views. ACounter. With.

Controller with Console and JOption View and Controller package controllers; import views. ACounter. With. Console. And. JOption. View; import java. io. IOException; public class ACounter. With. Console. And. JOption. View. And. Controller extends ACounter. With. Console. And. JOption. View implements Counter. With. Console. View. And. Controller { public void process. Input() { while (true) { int next. Input = Console. read. Int(); if (next. Input == 0) return; add(next. Input); } } }

Alternative: Delegation-based Configuration An. Observable Counter ACounter. Console View ACounter. Controller AConsole. Controller. And.

Alternative: Delegation-based Configuration An. Observable Counter ACounter. Console View ACounter. Controller AConsole. Controller. And. View ACounter. JOption View

Alternative: Inheritance-based MVC ACounter. With. Console. View. And. Controller New class

Alternative: Inheritance-based MVC ACounter. With. Console. View. And. Controller New class

Controller with Console and View and Controller package controllers; import views. ACounter. With. Console.

Controller with Console and View and Controller package controllers; import views. ACounter. With. Console. And. JOption. View; import java. io. IOException; public class ACounter. With. Console. View. And. Controller extends ACounter. With. Console. View implements Counter. With. Console. View. And. Controller { public void process. Input() { while (true) { int next. Input = Console. read. Int(); if (next. Input == 0) return; add(next. Input); } Only difference between } it and previous inheriting } controller

Inheritance vs. Delegation: Distribution Data and methods of both classes at one location Reused

Inheritance vs. Delegation: Distribution Data and methods of both classes at one location Reused Class Reusing Class instance Reused Class instance Reusing Class instance Can be in two different locations (client/server)

Reusing multiple classes Reused Class 1 Reused Class 2 Reusing Class Reused Class 1

Reusing multiple classes Reused Class 1 Reused Class 2 Reusing Class Reused Class 1 Reusing Class • In Java reusing multiple classes through inheritance not an option. • Can always have multiple instance variables

Pros and Cons of Delegation • Can change reused class without changing reusing class.

Pros and Cons of Delegation • Can change reused class without changing reusing class. • Multiple reusing classes can share reused class variables simultaneously. • Variables and methods of reusing and reused class can be on separate computers. • Works in single inheritance languages • Need to instantiate multiple classes. • Need to compose instances. • Need to define stub methods • Access problems Need to weigh pros and cons When benefits of delegation don’t apply use inheritance That is why inheritance exists.

Inheritance is a bad idea • If reusing class has “with” in its name:

Inheritance is a bad idea • If reusing class has “with” in its name: – ACounter. With. Console. View • If more than one way to do inheritance – Controller can be subclass of view – Or vice versa • If some of the inherited methods are not used: – AString. History extends Vector • Adds methods to add and access string elements rather than object elements • add. String(), string. At() – does not use remove. Element() etc • If reusing class should not be used wherever shared class is used – even if all methods are reused.

Inheritance is a bad idea public ACartesian. Point implements Point { int x, y;

Inheritance is a bad idea public ACartesian. Point implements Point { int x, y; public APoint(int the. X, int the. Y) { x = the. X; y = the. Y; } public int get. X() { return x } public int get. Y() { return y } public double get. Radius() { return Math. sqrt(x*x + y*y); }. public double get. Angle() { return Math. atan(y/x); } } public ASquare implements Square { Point center; int side. Length; public ASquare( Point the. Center, int the. Side. Length) { center = the. Center; side. Length = the. Side. Length; } public int get. X() {return center. get. X(); } public int get. Y() {return center. get. Y(); } public int get. Radius() {return center. get. Radius(); } public int get. Angle() {return center. get. Angle(); } public int get. Side. Length() {return side. Length; } } public ASquare extends ACartesian. Point implements Square { int side. Length; public ASquare (int the. X, int the. Y, int the. Side. Length) { x = the. X; y = the. Y; side. Length = the. Side. Length} public int get. Side. Length() {return side. Length}; } ASquare IS-NOTA ACartesian. Point!

Inheritance vs. Delegation in Popular Software: Toolkits Widget Class declares Action Performed super call

Inheritance vs. Delegation in Popular Software: Toolkits Widget Class declares Action Performed super call Widget User Widget Class declares Action Performed delegate call Widget User declares Java 1. 0 Later versions Action Performed

Inheritance vs. Delegation in Popular Software • Main problem with inheritance based widgets –

Inheritance vs. Delegation in Popular Software • Main problem with inheritance based widgets – Widget users could not be subclass of any other class because of multiple inheritance • Multiple objects can receive events from same widget. • Widget implementation can be switched • Observer concept supports both approaches – Inherited Observer class vs. Delegated Property. Change. Support • Threads support both approaches – Inheritable Thread class vs. Implemented Runnable Interface

The Importance of Being Earnest public class ABank. Account implements Bank. Account { int

The Importance of Being Earnest public class ABank. Account implements Bank. Account { int current. Balance = 0; public static final int MIN_BALANCE = 100; public ABank. Account (int initial. Balance) { current. Balance = initial. Balance; } public void deposit (int amount) { current. Balance += amount; } public boolean withdraw (int amount) { int min. Necessary. Balance = MIN_BALANCE + amount; if (min. Necessary. Balance <= current. Balance) { current. Balance -= amount; return true; } else return false; } public int get. Current. Balance () { return current. Balance; } public boolean safe. Withdraw (int amount) { An. Asserter. assert(amount > 0, "amount < 0"); boolean ret. Val = withdraw(amount); An. Asserter. assert(current. Balance >= MIN_BALANCE, "current. Balance < MIN_BALANCE"); return ret. Val;

Usage

Usage

Usage

Usage

Usage Integer. MAX_INT

Usage Integer. MAX_INT

Usage

Usage

Usage

Usage

Safe Usage

Safe Usage

Integer Overflow and Security • Google for “integer overflow security”

Integer Overflow and Security • Google for “integer overflow security”