Presentation is loading. Please wait.

Presentation is loading. Please wait.

Guidelines for class design Horstmann ch. 3.2-3.6 Noter ch.1.1.

Similar presentations


Presentation on theme: "Guidelines for class design Horstmann ch. 3.2-3.6 Noter ch.1.1."— Presentation transcript:

1 Guidelines for class design Horstmann ch. 3.2-3.6 Noter ch.1.1

2 Guidelines for class design Encapsulation Programming by contract Quality of class interface

3 Encapsulation no public instance variables accessors and mutators

4 One class – several implementations Example Day class –Day encapsulates a day in a fixed location –Use Gregorian calendar Answer questions such as –How many days are there between now and the end of the year? –What day is 100 days from now? Class Day: Custom class, for teaching/learning purpose Use the standard library classes, not this class, in your own programs

5 Designing a Day class Constructor Day(int year, int month, int date) Accessors getYear, getMonth, getDate Other methods –daysFrom computes number of days between two days: int n = today.daysFrom(birthday); –addDays computes a day that is some days away from a given day: Day later = today.addDays(999);

6 Day class: Implementation 1 Straightforward implementation: private int year private int month private int date addDays/daysFrom tedious to implement –April, June, September, November have 30 days –February has 28 days, except in leap years it has 29 days –All other months have 31 days –Leap years are divisible by 4, except after 1582, years divisible by 100 but not 400 are not leap years –There is no year 0; year 1 is preceded by year -1 –In the switchover to the Gregorian calendar, ten days were dropped: October 15, 1582 is preceded by October 4

7 Day class: Implementation 2 For greater efficiency, use Julian day number –Used in astronomy –Number of days since Jan. 1, 4713 BCE –May 23, 1968 = Julian Day 2,440,000 private int julian; Greatly simplifies date arithmetic public int daysFrom(Day other) { return julian - other.julian; } But constructor and accessor inefficient

8 No public instance variables Public instance variables would have blocked change of implementation –Can't just use text editor to replace all d.year with d.getYear() –How about d.year++? d = new Day(d.getYear() + 1, d.getMonth(), d.getDay()) –Ugh--that gets really inefficient in Julian representation Don't use public fields, even for "simple" classes

9 QUIZ In which lines should visibility modifier be changed? 1.none 2.a 3.b 4.c 5.a+b 6.a+c 7.b+c 8.a+b+c 9.I don’t know public class Measures { a) public static final int SIZE = 3; b) public int length = 2; c) static int height = 4; }

10 Encapsulation no public instance variables accessors and mutators

11 Accessors and Mutators Accessor: Reads object state without changing it Mutator: Changes object state Class without mutators is immutable String is immutable

12 Don't Supply a Mutator for every Accessor Day has getYear, getMonth, getDate accessors Day does not have setYear, setMonth, setDate mutators These mutators would not work well –Example: Day deadline = new Day(2004, 1, 31); deadline.setMonth(2); // ERROR deadline.setDate(28); –Maybe we should call setDate first? Day deadline = new Day(2004, 2, 28); deadline.setDate(31); // ERROR deadline.setMonth(3); Immutability is useful

13 Sharing Mutable References References to immutable objects can be freely shared Don't share mutable references Example class Employee {... private Date hireDate; public Date getHireDate() { return hireDate; } } Pitfall: Employee harry =...; Date d = harry.getHireDate(); d.setTime(t); // changes Harry's state!!! Remedy: Use clone public Date getHireDate() { return (Date)hireDate.clone(); }

14 Separating Accessors and Mutators If we call a method to access an object, we don't expect the object to mutate Rule of thumb: Mutators should return void Example of violation: StringTokenizer t =...; String s = t.nextToken(); Yields current token and advances iteration What if I want to read the current token again?

15 Better interface: String getToken(); void nextToken(); Even more convenient: String getToken(); String nextToken(); // returns current Refine rule of thumb: Mutators can return a convenience value, provided there is also an accessor to get the same value

16 Side effects Accessor: no change to object Mutator: changes object state Side effect: change to another object –Parameter variable public void print(Employee e) {... e.getHireDate().setTime(t);... } Avoid side effects--they confuse users Good example, no side effect: a.addAll(b) mutates a but not b

17 QUIZ Which methods/constructors need be removed to make Bucket immutable? 1.none 2.a 3.b 4.c 5.a+b 6.a+c 7.b+c 8.a+b+c 9.I don’t know public class Bucket { private int size = 1; public Bucket(int s) {size=s;} public Bucket() {size++;} public void enlarge() { size++; } public Bucket enlarge() { return new Bucket(size+1); } a) c) b)

18 Programming by Contract Example: Queue Precondition Assertion Postcondition Implementation Invariant

19 Queue People waiting to be served in a cafeteria Processes waiting to get CPU-time on a computer food in a supermarket (at least the shop owner wants the customer to take the old stuff first)

20 Queue a queue consists of some objects placed one after the other (ordered). a new object may be placed in the rear, behind all the others the object in the front may be removed FIFO = First In First Out

21 Queue implementation 1 using ArrayList public class Queue { public Queue() { elements = new ArrayList (); } public void add(T x) { elements.add(x); } public T remove() { return elements.remove(0); } public T peek() { return elements.get(0); } public int size() { return elements.size(); } private ArrayList elements; }

22 Queue implementation 2 using Circular Array Circular: head, tail indexes wrap around Avoids inefficient shifting of elements

23 Programming by Contract Example: Queue Precondition Assertion Postcondition Implementation Invariant

24 Programming by contracts: Preconditions Caller attempts to remove element from empty Queue What should happen? –Queue can declare this as an error –Queue can tolerate call and return dummy value What is better? –Excessive error checking is costly –Returning dummy values can complicate testing Contract metaphor –Service provider must specify preconditions –If precondition is fulfilled, service provider must work correctly –Otherwise, service provider can do anything When precondition fails, service provider may –throw exception –return false answer –corrupt data

25 Precondition Precondition for remove: size() > 0 Queue implementation 1 using ArrayList: public T remove() { return elements.remove(0); } What happens if precondition not fulfilled? IndexOutOfBoundsException

26 Precondition Precondition for remove: size() > 0 Queue implementation 2 using circular array: public T remove() { T r = elements[head]; head = (head + 1) % elements.length; count--; return r; } What happens if precondition not fulfilled? Queue is corrupted

27 Exceptions in the Contract /**... @throws IllegalArgumentException if queue is empty */ public Message remove() { if (size() == 0) throw new IllegalArgumentException();... } Exception throw part of the contract Caller can rely on behavior Exception throw not result of precondition violation This method has no precondition

28 QUIZ For which precondition(s) does method peek satisfy its contract? 1.Any (no precondition needed) 2.PRECOND: size()>0; 3.PRECOND: add(…) has been called earlier 4.PRECOND: remove() has never been called 5.Some other distinct precondition 6.None (method is wrong for all preconditions) 7.I don’t know Public class Queue { private ArrayList elements; … /** @precondition PRECOND @return element at head of queue */ public T peek() { return elements.get(0); }

29 Programming by Contract Example: Queue Precondition Assertion Postcondition Implementation Invariant

30 Assertions Syntax: assert condition; assert condition : explanation; Throws AssertionError if condition false and checking enabled Enable assertion checking during testing with java -ea MyProg Useful for warning programmers about precondition failure

31 Assertion public Message remove() { assert size() > 0 : "violated precondition size() > 0";... }

32 Programming by Contract Example: Queue Precondition Assertion Postcondition Implementation Invariant

33 Postconditions Conditions that the service provider guarantees Example: add method @postcondition size() > 0 Postcondition of one call can imply precondition of another: q.add(m1); m2 = q.remove();

34 Pre- and post-conditions /** @param n integer @precondition n >= 0 @return integer squareroot a of n @postcondition a*a <= n && n < (a+1)*(a+1) */ public int intSquareRoot(int n) { assert n >= 0; int a = n; int b = 1; while (a>b) { a = (a+b)/2; b = n/a; } assert (a*a <= n && n < (a+1)*(a+1)); return a; } responsibility of caller to ensure precondition responsibility of implementor to ensure postcondition

35 QUIZ Which code at ? 1.A 2.B 3.C 4.D 5.None of A-D 6.Several of A-D boolean result = true; for (int i=1; i<list.size(); i++) if (list.get(i-1)>list.get(i)) result = false; else result = true; return result; for (int i=1; i<list.size(); i++) if (list.get(i-1)>list.get(i)) return false; else return true; for (int i=1; i<list.size(); i++) if (list.get(i-1)>list.get(i)) return false; return true; for (int i=0; i<list.size(); i++) if (list.get(i)>list.get(i+1)) return false; return true; /** @param list of numbers @return true precisely when list is sorted (in increasing order) */ public boolean sorted(List list) { } A B C D Postcondition! 7. I don’t know

36 Programming by Contract Example: Queue Precondition Assertion Postcondition Implementation Invariant

37 Condition that –involves details of particular implementation –is true after every constructor –is preserved by every method (if it's true before the call, it's again true afterwards) example: Box

38 Implementation invariant: class Box Methods for class Box: –fitsIn : Decide whether box fits within another box under 90 deg rotations –combine : Compute minimum enclosing box of this box and another box

39 Implementation invariant: class Box /** IMPLEMENTATION INVARIANT: x <= y <= z */ private int x,y,z; Invariant true after constructor public Box(int w, int h, int d) { x = w; y = h; z = d; while (x>y || y>z) { if (x>y) { int temp = x; x = y; y = temp; } if (y>z) { int temp = y; y = z; z = temp; } } sort dimensions to satisfy invariant represents height, width and depth

40 Implementation invariant: class Box Implementation invariant is true before method call –simplifies implementation public boolean fitsIn(Box b) { return ( x<=b.x && y<=b.y && z<=b.z ); } public Box combine(Box b) { return new Box(Math.max(x,b.x), Math.max(y,b.y), Math.max(z,b.z)); }

41 Implementation invariant: class Box Without implementation invariant: –Complicated implementation necessary –more error prone public boolean fitsIn(Box b) { return ( (x<=b.x && y<=b.y && z<=b.z) || (x<=b.x && z<=b.y && y<=b.z) || (y<=b.x && x<=b.y && z<=b.z) || (y<=b.x && z<=b.y && x<=b.z) || (z<=b.x && x<=b.y && y<=b.z) || (z<=b.x && y<=b.y && x<=b.z) ); }

42 QUIZ Which methods satisfy the invariant? 1.a and b 2.a only 3.b only 4.Neither 5.I don’t know public class Time { //INVARIANT 0 <= hour < 24 private int hour; public Time(int h) {hour = h;} public void increment() { hour = (hour+1) % 24; } public void increment2() { if (hour==23) hour = 0; else hour++; } a) b)

43 QUIZ Where should asserts be used to verify the invariant?? 1.A,B, C,D, E,F,G 2.A,B, C,D, E,G 3.B,D,F 4.B,D,G 5.A,B, C,D 6.B,D 7.Some other combination 8.I don’t know public class Time { //INVARIANT 0 <= hour < 24 private int hour; public Time(int h) { hour = h; } public void increment() { hour = (hour+1) % 24; } public int getMinutes() { int res = 60*hour; return result; } A F E G D C B

44 Quality of Class Interface Cohesion Completeness Convenience Clarity Consistency

45 Cohesion Class describes a single abstraction Methods should be related to the single abstraction Bad example: public class Mailbox { public addMessage(Message aMessage) {... } public Message getCurrentMessage() {... } public Message removeCurrentMessage() {... } public void processCommand(String command) {... }... } processCommand does not belong here

46 Completeness Support operations that are well-defined on abstraction Potentially bad example: Date Date start = new Date(); // do some work Date end = new Date(); How many milliseconds have elapsed? No such operation in Date class Does it fall outside the responsibility? After all, we have before, after, getTime

47 Convenience A good interface makes all tasks possible... and common tasks simple Bad example: Reading from System.in Why doesn't System.in have a readLine method? After all, System.out has println.

48 Clarity Confused programmers write buggy code Bad example: Removing elements from LinkedList Reminder: Standard linked list class LinkedList countries = new LinkedList (); countries.add("A"); countries.add("B"); countries.add("C"); Iterate through list: ListIterator iterator = countries.listIterator(); while (iterator.hasNext()) System.out.println(iterator.next());

49 Clarity Iterator between elements Like blinking caret in word processor add adds to the left of iterator (like word processor): Add X before B: ListIterator iterator = countries.listIterator(); // |ABC iterator.next(); // A|BC iterator.add("France"); // AX|BC To remove first two elements, you can't just "backspace" remove does not remove element to the left of iterator From API documentation: Removes from the list the last element that was returned by next or previous. This call can only be made once per call to next or previous. It can be made only if add has not been called after the last call to next or previous. Not clear

50 Consistency Related features of a class should have matching –names –parameters –return values –behavior Bad example: –String class s.equals(t) / s.equalsIgnoreCase(t) –But boolean regionMatches (int toffset, String other, int ooffset, int len) boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) –Why not regionMatchesIgnoreCase ?


Download ppt "Guidelines for class design Horstmann ch. 3.2-3.6 Noter ch.1.1."

Similar presentations


Ads by Google