Presentation is loading. Please wait.

Presentation is loading. Please wait.

Assertions Prasun Dewan Comp 114. Assertions Declare some property of the program Used for – formal correctness – testing – documentation – specification.

Similar presentations


Presentation on theme: "Assertions Prasun Dewan Comp 114. Assertions Declare some property of the program Used for – formal correctness – testing – documentation – specification."— Presentation transcript:

1 Assertions Prasun Dewan Comp 114

2 Assertions Declare some property of the program Used for – formal correctness – testing – documentation – specification

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

4 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

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

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

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

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

9 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.

10 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

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

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

13 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

14 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

15 Recording Variables Cannot say: {X = X + 1} assert X == X + 1; Introduce recording variable {oldX = X; X = X + 1} assert X = oldX + 1 Special variables needed to make assertions sometimes

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

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

18 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

19 Alternative precondition pre (x > 0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5} Some assertions imply others –x > 0  x !=0 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

20 Alternative postcondition pre (x != 0) post (z == 5) { y = 10/x; z = 5} Some assertions imply others –y == 10/x & (z == 5) => 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.

21 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

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

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

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

25 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?”

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

27 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.

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

29 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

30 Debugging/ specification/ documentation point of view pre true post true { y = 10/x; z = 5} pre true post true { y = 10/x;} Statements are not equivalent Not the best pre and post conditions

31 Debugging/ specification/ documentation point of view pre false post false { y = 10/x; z = 5} pre false post false { y = 10/x;} Statements are not equivalent Not the best pre and post conditions

32 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

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

34 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

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

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

37 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.

38 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.

39 Strongest possible condition Implies anything false false  p If false is true then p is true But false is never true. So any p is implied. “I will do this when hell freezes over”

40 Important equivalence P  Q  !P | Q P  true  !P | true  true false  Q  !false | Q  true

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

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

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

44 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

45 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.

46 Loop Invariant (edited) 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.

47 Loop Invariant inv (sum =  0 j k) & (j = 0) 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.

48 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

49 Class assertions (edit) public class C { int x =0; int y = 1; public void incrementXAndY () { incrementX(); incrementY(); } public int getX() { return x;} public int getY() { return y;} incrementX() { x++;} incrementY() { y++;} } Preconditions, postconditions, invariants shared by all public methods of class

50 Class invariant (edited) public class C { int x =0; int y = 1; public void incrementXAndY () { incrementX(); incrementY(); } public int getX() { return x;} public int getY() { return y;} incrementX() { x++;} incrementY() { y++;} } Preconditions, postconditions, invariants shared by all public methods of class

51 Class assertions invariant y == x + 1 public class C { int x =0; int y = 1; public void incrementXAndY () { incrementX(); incrementY(); } public int getX() { return x;} public int getY() { return y;} incrementX() { x++;} incrementY() { y++;} } Preconditions, postconditions, invariants shared by all public methods of class

52 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

53 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

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

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

56 Quantified Propositions Sub-proposition –Simple or quantified proposition in terms of quantifier Domain –A collection of values used in sub-proposition evaluation –b.elementAt(0), … b.elementAt(B.size() – 1 Domain description –Describes domain using quantified variable Quantified –  j: 0 <= j < b.size(): b.elementAt(j) != null –  j: 0 <= j < b.size(): b.elementAt(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

57 Expressing Assertions in Java Write your own code. Libraries Language support –Does not support quantifiers –Works for 1.4 –You have 1.3

58 Assertion Failed Exception Thrown when assertion fails Unchecked because internal error Can subclass it for specific assertions Will use message in examples package assertions; public class AnAssertionFailedException extends RuntimeException { public AnAssertionFailedException () {}; public AnAssertionFailedException (String initValue) { super (initValue); }

59 Assert methods Used for simple assertions package assertions; import java.util.Enumeration; public class AnAsserter { public static void assert (boolean proposition, String message) throws AnAssertionFailedException { if (!proposition) throw new AnAssertionFailedException (message); } public static void assert (boolean proposition) throws AnAssertionFailedException { assert (proposition, “”); }

60 Using assert 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 //inv (sum =  0 j k) & (j = 0) sum = 0; j = 0; while (j < n) { j++; sum = sum + j; }

61 Using assert 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 sum = 0; j = 0; //inv (sum =  0 j k) & (j = 0) while (j < n) { AnAsserter.assert (j = 0 && sum == sum(0, j)) j++; sum = sum + j; AnAsserter.assert (j =0 && sum == sum(0, j)) }

62 Class and Method Invariants Class invariant –Encode them as invariants of all public methods. Method invariant –Put assert at start and end of method //inv y = x + 1 public class C { int x =0; int y = 1; public void incrementXAndY () { incrementX(); incrementY(); } public int getX() { return x;} public int getY() { return y;} incrementX() { x++;} incrementY() { y++;} }

63 Class and Method Invariants Class invariant –Encode them as invariants of all public methods. Method invariant –Put assert at start and end of method –Can define another proxy method that asserts and calls the real method Keeps asserting code separate Useful when multiple exit points //inv y = x + 1 public class C { int x =0; int y = 1; void assertClassInvariant{ AnAsserter.assert (y == x + 1); } void internalIncrementXAndY () { incrementX(); incrementY(); } public void incrementXAndY () { assertClassInvariant(); internalIncrementXAndY(); assertClassInvariant(); } int internalGetX() { return x; } public int getX() { assertClassInvariant(); int retVal = internalGetX(); assertClassInvariant(); return retVal; } … } Asserting proxy method

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

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

66 Goal Need to fill the … package assertions; import java.util.Enumeration; public class AQuantifier { public static boolean forAll (…) { … } public static boolean thereExists (…) { … }

67 Problem with inaccessible variables Syntax –Qx:D(x):P(x) –  j: 0 <= j < b.size(): b.elementAt(j) != null –  j: 0 <= j < b.size(): b.elementAt(j) != null How to describe D(x) and P(x)? –Cannot pass the expressions as variables involved not visible to library –Will pass one argument describing the domain Collection of elements –Another argument describing the subproposition to be evaluated for each domain element.

68 How to describe domain? Syntax –Qx:D(x):P(x) –  j: 0 <= j < b.size(): b.elementAt(j) != null –  j: 0 <= j < b.size(): b.elementAt(j) != null Domain can be –Array, Vector, StringHistory, … Need a common interface to describe elements –java.util.Enumeration

69 Describing the domain AnAsserter.assert(AQuantifier.forAll(B.elements(), …, "Some element of B is null"); AnAsserter.assert(AQuantifier.thereExists(b.elements(), …, "All elements of B are null"); Need to fill … package assertions; import java.util.Enumeration; public class AQuantifier { public static boolean forAll ((Enumeration domain, …) { while (domain.hasMoreElements()) … } public static boolean thereExists ((Enumeration domain, …) { while (domain.hasMoreElements()) … }

70 How to describe Subproposition Syntax –Qx:D(x):P(x) –  j: 0 <= j < b.size(): b.elementAt(j) != null –  j: 0 <= j < b.size(): b.elementAt(j) != null Cannot pass expression string. But can pass function that evaluates it. –boolean isNotNull(Object element) { return element != null; } Function will be evaluated for each domain element by our libraries

71 Subproposition as a function AnAsserter.assert(AQuantifier.forAll(B.elements(), isNotNull), "Some element of B is null"); AnAsserter.assert(AQuantifier.thereExists(b.elements(), isNotNull), "All elements of B are null"); package assertions; import java.util.Enumeration; public class AQuantifier { public static boolean forAll (Enumeration domain, (object  boolean) subProposition) { while (domain.hasMoreElements()) if (!subProposition (domain.nextElement()) return false; return true; } public static boolean thereExists ((Enumeration domain, (object  boolean) subProposition) { while (domain.hasMoreElements()) if (!subProposition (domain.nextElement()) return true; return false; }

72 How to describe Subproposition Cannot pass expression string. But can pass function that evaluates it. –boolean isNotNull(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 package visitors; import assertions.ElementChecker; public class ANonNullChecker implements ElementChecker { public boolean visit(Object element) { return (element != null); } package assertions; public interface ElementChecker { public boolean visit (Object element); }

73 Describing the subproposition AnAsserter.assert(AQuantifier.forAll(b.elements(), new ANonNullChecker()), "Some element of B is null"); AnAsserter.assert(AQuantifier.thereExists(b.elements(), new ANonNullChecker()), "All elements of B are null"); package assertions; import java.util.Enumeration; public class AQuantifier { public static boolean forAll (Enumeration domain, ElementChecker subProposition) { while (domain.hasMoreElements()) if (!subProposition.visit(domain.nextElement())) return false; return true; } public static boolean thereExists (Enumeration domain, ElementChecker subProposition) { while (domain.hasMoreElements()) if (subProposition.visit(domain.nextElement())) return true; return false; }

74 Subproposition accessing vars other than domain elements  j: 0 <= j < b.size(): b.elementAt(j) != a.elementAt(0)  j: 0 <= j < b.size(): b.elementAt(j) != a.elementAt(0) package visitors; import assertions.ElementChecker; public class AnInequalityChecker implements ElementChecker { Object testObject; public AnInequalityChecker(Object theTestObject) { testObject = theTestObject; } public boolean visit(Object element) { return !element.equals(testObject); } AnAsserter.assert(AQuantifier.forAll(b.elements(), new AnInequalityChecker(a.elementAt(0))), "Some element of b is equal to a.elementAt(0)"); Each external var becomes constructor parameter

75 Visitor Pattern Some collection C of elements of type T Visitor interface –public interface V {public T2 m (T p);} One or more traverser methods that use collection and visitor interface to pass one or more collection elements to the method. traverser1 (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 AV1 implements V { public AV1 (T1 p1, … Tn pN) { …} public T2 m (T p) { … } } Client passes traverser visitor implementation and collection traverser1(c, new AV1(a1,.. aN))

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

77 Example of Visitor Pattern Enumeration Object component ElementChecker ANonNull Checker implements AnInequality Checker uses thereExists() forAll()

78 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.

79 Java 1.4 Assertion Support AssertionError exception = AnAssertionFailedException assert = AnAsserter.assert(, “”); assert : = AnAsserter.assert(, string representation of Assertions can be dynamically turned on or off. No support for quantifiers. In 1.3 assert is a keyword but has no implementation

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

81 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.

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

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

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

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

86 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

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

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

89 Delegating Proxy-based Counter package models; import assertions.AnAsserter; public class ADelegatingCheckedCounter implements Counter { Counter counter; public ADelegatingCheckedCounter (Counter theCounter) { counter = theCounter; } public void add (int amount) { int oldVal = counter.getValue(); counter.add(amount); int newVal = counter.getValue(); AnAsserter.assert(newVal == oldVal + amount, "New counter:" + newVal + " != old counter:" + oldVal + " + amount:" + amount); } public int getValue() { return counter.getValue()b; }

90 Example of Delegating Proxy ACounter Counter implements AChecked Counter HAS_A implements

91 Delegating Proxy Real Subject Class Subject Interface implements Proxy Class Has-A implements

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

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

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

95 Inheritance vs. Delegation Reused ClassReused Interface Reusing ClassReusing Interface Reused ClassReused Interface Reusing ClassReusing Interface

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

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

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

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

100 Delegating Proxy-based Counter package models; import assertions.AnAsserter; public class ADelegatingCheckedCounter implements Counter { Counter counter; public ADelegatingCheckedCounter (Counter theCounter) { counter = theCounter; } public void add (int amount) { int oldVal = counter.getValue(); counter.add(amount); int newVal = counter.getValue(); AnAsserter.assert(newVal == oldVal + amount, "New counter:" + newVal + " != old counter:" + oldVal + " + amount:" + amount); } public int getValue() { return counter.getValue()b; }

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

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

103 Delegating Proxy-based Counter package models; import assertions.AnAsserter; public class ADelegatingCheckedCounter implements Counter { Counter counter; public ADelegatingCheckedCounter (Counter theCounter) { init(theCounter); } public void add (int amount) { int oldVal = counter.getValue(); counter.add(amount); int newVal = counter.getValue(); AnAsserter.assert(newVal == oldVal + amount, "New counter:" + newVal + " != old counter:" + oldVal + " + amount:" + amount); } public int getValue() { return counter.getValue(); }

104 Inheritance vs. Delegation: Overridden Methods Reused Class Reusing Class Reused Class Reusing Class declares Reused method m declares Overriding method m declares

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

106 Delegating Proxy-based Counter package models; import assertions.AnAsserter; public class ADelegatingCheckedCounter implements Counter { Counter counter; public ADelegatingCheckedCounter (Counter theCounter) { init(theCounter); } public void add (int amount) { int oldVal = counter.getValue(); counter.add(amount); int newVal = counter.getValue(); AnAsserter.assert(newVal == oldVal + amount, "New counter:" + newVal + " != old counter:" + oldVal + " + amount:" + amount); } public int getValue() { return counter.getValue(); }

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

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

109 Delegating Proxy-based Counter package models; import assertions.AnAsserter; public class ADelegatingCheckedCounter implements Counter { Counter counter; public ADelegatingCheckedCounter (Counter theCounter) { init(theCounter); } public void add (int amount) { int oldVal = counter.getValue(); counter.add(amount); int newVal = counter.getValue(); AnAsserter.assert(newVal == oldVal + amount, "New counter:" + newVal + " != old counter:" + oldVal + " + amount:" + amount); } public int getValue() { return counter.getValue(); }

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

111 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 –not useful if no calls are made

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

113 public abstract class AnAbstractTitleToCourseMapper implements TitleToCourseMapper { public AnAbstractTitleToCourseMapper() { fillCourses(); } abstract RegularCourse getRegularCourse(); abstract FreshmanSeminar getFreshmanSeminar(); void fillCourses() { RegularCourse introProg = getRegularCourse (); FreshmanSeminar legoRobots = getFreshmanSeminar();... } public String getTitle() { return titleToCourseMapper.getTitle(); }... } Abstract class

114 Concrete course user public class ATitleToCourseMapper extends AnAbstractTitleToCourseMapper { RegularCourse getRegularCourse() { return new ARegularCourse(); } FreshmanSeminar getFreshmanSeminar() { return new AFreshmanSeminar(); }

115 Delegate class public class ATitleToCourseMapperDelegate implements TitleToCourseMapper { CourseFactory delegator; public ATitleToCourseMapperDelegate(CourseFactory theDelegator) { delegator = theDelegator; fillCourses(); } void fillCourses() { RegularCourse introProg = delegator.getRegularCourse (); FreshmanSeminar legoRobots = delegator. getFreshmanSeminar();... } public String getTitle() { return titleToCourseMapper.getTitle(); }... }

116 Concrete course user public class ATitleToCourseMapperDelegator implements TitleToCourseMapper, CourseFactory{ public RegularCourse getRegularCourse() { return new ARegularCourse(); } public FreshmanSeminar getFreshmanSeminar() { return new AFreshmanSeminar(); } public String getTitle() { return titleToCourseMapper.getTitle(); }... }

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

118 Inheriting String Database public class AStringDatabase extends AStringHistory implements StringDatabase { public void deleteElement (String element) { shiftUp(indexOf(element)); } public int indexOf (String element) { int index = 0; while ((index < size) && !element.equals(contents[index])) index++; return index; } void shiftUp (int startIndex) { int index = startIndex ; while (index + 1 < size) { contents[index] = contents[index + 1]; index++; } size--; } public boolean member(String element) { return indexOf (element) < size; } public void clear() { size = 0; }

119 Delegating String Set package collections; import enums.StringEnumeration; public class ADelegatingStringDatabase implements StringDatabase { AStringHistory stringHistory = new AStringHistory(); public void deleteElement (String element) { shiftUp(indexOf(element)); } public int indexOf (String element) { int index = 0; while ((index < stringHistory.size) && !element.equals(stringHistory.contents[index])) index++; return index; } void shiftUp (int startIndex) { int index = startIndex ; while (index + 1 < stringHistory.size) { stringHistory.contents[index] = stringHistory.contents[index + 1]; index++; } stringHistory.size--; } Class as type and accessing non public variables in same package Instantiating delegate rather than getting reference from constructor.init method

120 Delegating String Set public boolean member(String element) { return indexOf (element) < stringHistory.size; } public void clear() { stringHistory.size = 0; } public int size() { return stringHistory.size(); } public String elementAt (int index) { return stringHistory.elementAt(index); } public StringEnumeration elements() { return stringHistory.elements(); } public void addElement(String element) { stringHistory.addElement(element); } Large number of forwarding stubs

121 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

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

123 Pros of Delegation Reused ClassReused Interface Reusing ClassReusing Interface Reused ClassReused Interface Reusing ClassReusing Interface

124 Substituting Reused Class Reused Class 2Reused Interface Reusing Class 2Reusing Interface Reused Class 2Reused Interface Reusing ClassReusing Interface

125 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

126 New Inheriting Proxy Class package models; import assertions.AnAsserter; public class ACheckedCounter2 extends ACounter2 { public void add (int amount) { int oldCounter = counter; super.add(amount); AnAsserter.assert(counter == oldCounter + amount, "New counter:" + counter + " != old counter:" + oldCounter + " + amount:" + amount); }

127 Orginal Delegating Proxy package models; import assertions.AnAsserter; public class ADelegatingCheckedCounter implements Counter { Counter counter; public ADelegatingCheckedCounter (Counter theCounter) { counter = theCounter; } public void add (int amount) { int oldVal = counter.getValue(); counter.add(amount); int newVal = counter.getValue(); AnAsserter.assert(newVal == oldVal + amount, "New counter:" + newVal + " != old counter:" + oldVal + " + amount:" + amount); } public int getValue() { return counter.getValue(); }

128 Multiple Reusing Classes Reused Class Reusing Class 1 Reused Class Reusing Class 1

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

130 AConsoleControllerAndViewAndJOptionView AConsoleControllerAndView ACounterJOption View Delegation-based MVC ACheckedCounter ACounterController ACounterConsole View

131 Inheritance-based MVC ACounter ACounterWithConsoleAndJOptionViewAndController ACounterWithConsoleView ACounterWithConsoleAndJOptionView No facades or notification needed

132 Controller with Console View package views; import models.ACounter; public class ACounterWithConsoleView extends ACounter { void appendToConsole(int counterValue) { System.out.println("Counter: " + counterValue); } public void add (int amount) { super.add(amount); appendToConsole(getValue()); }

133 Controller with Console and JOption View package views; import models.ACounter; import javax.swing.JOptionPane; public class ACounterWithConsoleAndJOptionView extends ACounterWithConsoleView { void displayMessage(int counterValue) { JOptionPane.showMessageDialog(null, "Counter: " + counterValue); } public void add (int amount) { super.add(amount); displayMessage(getValue()); }

134 Controller with Console and JOption View and Controller package controllers; import views.ACounterWithConsoleAndJOptionView; import java.io.IOException; public class ACounterWithConsoleAndJOptionViewAndController extends ACounterWithConsoleAndJOptionView implements CounterWithConsoleViewAndController { public void processInput() { while (true) { int nextInput = Console.readInt(); if (nextInput == 0) return; add(nextInput); }

135 AConsoleControllerAndView Alternative: Delegation-based Configuration AnObservable Counter ACounterController ACounterConsole View ACounterJOption View

136 Alternative: Inheritance-based MVC ACounter ACounterWithConsoleViewAndController ACounterWithConsoleView New class

137 Controller with Console and View and Controller package controllers; import views.ACounterWithConsoleAndJOptionView; import java.io.IOException; public class ACounterWithConsoleViewAndController extends ACounterWithConsoleView implements CounterWithConsoleViewAndController { public void processInput() { while (true) { int nextInput = Console.readInt(); if (nextInput == 0) return; add(nextInput); } Only difference between it and previous inheriting controller

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

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

140 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.

141 Inheritance is a bad idea If reusing class has “with” in its name: –ACounterWithConsoleView 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: –AStringHistory extends Vector Adds methods to add and access string elements rather than object elements addString(), stringAt() –does not use removeElement() etc If reusing class should not be used wherever shared class is used –even if all methods are reused.

142 Inheritance is a bad idea public ACartesianPoint implements Point { int x, y; public APoint(int theX, int theY) { x = theX; y = theY;} public int getX() { return x } public int getY() { return y } public double getRadius() { return Math.sqrt(x*x + y*y); }.public double getAngle() { return Math.atan(y/x);} } public ASquare extends APoint implements Square { int sideLength; public ASquare (int theX, int theY, int theSideLength) { x = theX; y = theY; sideLength = theSideLength} public int getSideLength() {return sideLength}; } public ASquare extends APoint implements Square { Point center; int sideLength; public ASquare( Point theCenter, int theSideLength) { center = theCenter;sideLength = theSideLength; } public int getX() {return center.getX();} public int getY() {return center.getY();} public int getRadius() {return center.getRadius();} public int getAngle() {return center.getAngle();} public int getSideLength() {return sideLength;} } ARectangle IS- NOT-A ACartesianPoint!

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

144 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 supports both approaches –Inherited Observer class vs. Delegated PropertyChangeSupport Threads support both approaches –Inheritable Thread class vs. Implemented Runnable Interface


Download ppt "Assertions Prasun Dewan Comp 114. Assertions Declare some property of the program Used for – formal correctness – testing – documentation – specification."

Similar presentations


Ads by Google