Lec 31 [class design, programming by contract]

Download Lec 31 [class design, programming by contract]

Post on 29-Nov-2014




0 download

Embed Size (px)




<ul><li> 1. GuideLines For Class Design Rule 1 Make Attributes/Data Fields of class Private. Private data fields are essential for improving the implementation of a class without disruption to its users Rule 2 Dont Supply set methods / Mutator methods automatically for every instance field Supply set methods carefully Immutable classes have one great advantage over mutable classes. Their object references can be freely shared </li> <li> 2. GuideLines For Class Design cont Rule 3 Acessor Method should never return a reference to a mutable reference. However if required, Clone the field and return the cloned reference. It is safe to return primitive types and reference to immutable objects class Employee { private String name; private double salary; private Date hireDate; . public String getName() { return name; } public double getSalary() { return salary; } public Date getHireDate() { return hireDate;} } Immutable Reference mutable Reference </li> <li> 3. Employee harry = new Emplyoee(harry,4000,new date()); harry= Employee name=harry salary = 4000.00 hireDate = Date Date d = harry.getHireDate(); d= d.setTime(4000); Invalid Updation change getHireDate as follows: public Date getHireDate() { return (Date) hireDate.clone(); } Clone the mutable reference first and then return the cloned copy </li> <li> 4. Use of final instance fields You can use final fields to indicate that it does not change. Good way of expressing that a class in immutable. However final keyword only refers to the contents of reference variable not its state. Examples: final ArrayList ar = new ArrayList(); final BOX box = new BOX(10,6,8); Use of final only guarantee that reference is final and it can not point to another reference. But it does not guarantee that state of the object reference can not be changed. </li> <li> 5. Separation of Accessors and Mutators Keep the roles of accessor and mutator methods separate. Accessor method should not be allowed to change the state of the object. Mutator method should not be allowed to return any information about the state of the object. It should only be allowed to change the state of the object. </li> <li> 6. String str = "BITS C342,83,Object Oriented Programming,Lecture Section 3;MWF 9,Pankaj;Vyas,3160"; StringTokenizer strT1 = new StringTokenizer(str); // No Delimiters Specified System.out.println("Number Of Tokens :"+strT1.countTokens()); System.out.println("Individual Tokens"); while(strT1.hasMoreTokens()) System.out.println(strT1.nextToken()); Returns the next Token as well as moves the Token position forward </li> <li> 7. ArrayList ar = new ArrayList(); ar.add(new Integer(10)); ar.add(new Integer(20)); ar.add(new Integer(30)); Iterator itr = ar.iterator(); while(itr.hasNext()) { System.out.println ( itr.next() ); } Returns next element as well as moves the iterator to next element </li> <li> 8. Side Effects A method should not change the state/value of the Explicit parameter A method can change the state of the implicit parameter </li> <li> 9. Analyzing the Quality of an Interface 1.Cohesion 2.Completeteness 3.Convenience 4.Clarity 5.Consistency </li> <li> 10. Cohesion A class is cohesive if all methods belongs to a single abstraction A class is an abstraction of single concept. Operations in the class must logically fit together to support a single, coherent purpose. Cohesion Violation Example class MailBox { public void addMessage(Message m) { } public Message getCurrentMessage() { } public Message removeCurrentMessage() {} public void processCommand() {.} } Violates the principle of cohesion </li> <li> 11. Completeness A class interface should be complete It should support all operations that falls within abstraction scope Slightly Incomplete Example. Date class represents a point in time. You can have the methods to check whether a given date is after/before the other or not. How many milliseconds elapsed between two date objects d1 and d2. There is no direct method to compute the difference. But you use following methods to do the same: d1.getTime() d2.getTime() [ This is not a big flaw ] Almost all classes defined in java API are almost complete. </li> <li> 12. Convenience Interface should make common tasks easy. Java is Inconvenient to use for reading Strings from System.in How we read a string from System.in BufferedReader br = new BufferedReader (new InputStreamReader(System.in)) String name = br.readLine(); Multiple Degrees of Inconvenience are (i) Why System.in is not a BufferedReader (ii) Why there is not a readLine() method inside InputStreamReader (iii) Why user can not construct a BufferedReader w/o first making a InputStreamReader. </li> <li> 13. Clarity Interface Should be clear to the programmers. Reader should understand the operation by reading it from the documentation. Documentation of the interface operation should not generate confusion among programmers. Example : remove method in iterator. 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. </li> <li> 14. import java.util.*; class clarity { public static void main(String args[]) { LinkedList list = new LinkedList(); list.add("A"); list.add("B"); list.add("C"); // ABC ListIterator itr = list.listIterator(); // |ABC itr.next(); // A|BC itr.add("X"); // AX|BC // add method adds before the cursor itr.remove(); itr.remove(); } } /* Output Exception in thread "main" java.lang.IllegalStateException at java.util.LinkedList$ListItr.remove(LinkedList.java:590) at clarity.main(clarity.java:16) */ </li> <li> 15. Consistency Operations in a class should be consistent with each other w.r.t names, parameters and return values and behavior. Java has minor inconsistencies day in GregorianCalender can be specified as new GregorianCalender(year,month-1,day) month 0-11, day 1-31 Inconsistent Following pairs for string comparisons equals()/equalsIgnorecase() CompareTo/compareToIgnorecase Consistent Pairs boolean regionMatches(int toffset, String other, int offset, int len) boollean regionMatches(boolean ignorecase , ..) InConConsistent Pairs </li> <li> 16. Programming By Contract Helpful for following situations ( i ) Constructors should create only valid objects (ii) Mutator methods should preserve the state of the object (iii) Every method/operation should not waste time for checking invalid objects. These guarantees can be described by the use of Contract. Methods should be implemented as agents fulfilling the contract. Programming by contract has following elements: 1. Preconditions 3. Assertions 5. class Invariants 2. PostConditions 4. Exceptions </li> <li> 17. public class MessageQueue { // Instance Fields private Message[] elements; // elements stored in Message type Array private int head; // Gives head position from MessageQueue private int tail; // Gives tail position from MessageQueue private int count; // Gives count of the number of elements currently in Queue // Methods public MessageQueue(int capacity) { } // Constructor Method // removes the First Element and returns it public Message removeFirst() { } // returns the First Element public Message getFirst() { . } // adds a message in queue public void add(Message m) { . } // returns the size() of the queue public int getSize() { .. } { .} } </li> <li> 18. Preconditions Precondition of a method is a condition that must be fulfilled before the method may be called Method is a service provider (agent) and caller of the method is service requester. Checking a precondition is the responsibility of the caller or service requester. If a precondition is not true and the method is called then service provider may take any suitable action. Precondition should be defined such that caller can check the precondition before invoking the method. Example : Define preconditions for add and remove method Precondition for remove method </li> <li> 19. 1. Precondition for removeFirst() /** Removes message at head @return the message that has been removed from queue @precondition size() &gt; 0 */ public Message removeFirst() { } 2. Precondition for add(Message) /** Appends message at tail This is not valid @Param AMessage the message to be appended precondition as @precondition size() &lt; elements.length; elements is private */ field and can not public void add(Message M) be accessed { outside. } So define a method isFull() which is public returns true or false when queue is full or not. @precondition !isFull() </li> <li> 20. Assertions What actions is to be taken if a method is called with preconditions violated. Assertion mechanism alerts the user about violation of precondition. Java support assert statement (version 1.4 of Java SDK) for this purpose Assert statement has two forms Form 1: assert condition; Form 2 : assert condition : explanation If condition is true execution continues. If condition false then Assertion Error is thrown If condition is true execution continues. If condition false then Assertion Error is thrown with explanation explanation Is in the form of an String </li> <li> 21. Assertion cont By Default Assertions are disabled in Java Interpreter You can enable assertions by command java -ea java ea StudentTest </li> <li> 22. Exceptions in the Contract Assertions are new features. Before Assertions, precondition violation is dealt by throwing suitable exceptions Example : public removeFirst() { if( count </li> <li> 23. Exceptions cont Throwing Exception in case of precondition violation has one disadvantage Check for Exceptions can not be turned Off </li> <li> 24. Postconditions A post condition of a method is a condition that holds true after the method has completed. Postconditions are supposed to be fulfilled by methods called. Define Postcondition for add and removeFirst methods. Assertions can be used for checking postconditions. </li> <li> 25. Class Invariants A Condition that is to be fulfilled by all objects of the class after the completion of any method or constructor. Class invariant condition must be true before and after every method call. Invariant for MessageQueue 0</li></ul>