Lec 31 [class design, programming by contract]

27
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 “Don’t 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”

description

 

Transcript of Lec 31 [class design, programming by contract]

Page 1: Lec 31 [class design, programming by contract]

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 “Don’t 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”

Page 2: Lec 31 [class design, programming by contract]

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

Page 3: Lec 31 [class design, programming by contract]

Employee harry = new Emplyoee(“harry”,4000,new date());

harry=

Employee

name=“harry”salary = 4000.00hireDate =

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

Page 4: Lec 31 [class design, programming by contract]

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.

Page 5: Lec 31 [class design, programming by contract]

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.

Page 6: Lec 31 [class design, programming by contract]

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

Page 7: Lec 31 [class design, programming by contract]

ArrayList<Integer> ar = new ArrayList<Integer>();

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

Page 8: Lec 31 [class design, programming by contract]

Side Effects

• A method should not change the state/value of the Explicit parameter

• A method can change the state of the implicit parameter

Page 9: Lec 31 [class design, programming by contract]

Analyzing the Quality of an Interface

1.Cohesion2.Completeteness3.Convenience4.Clarity5.Consistency

Page 10: Lec 31 [class design, programming by contract]

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

Page 11: Lec 31 [class design, programming by contract]

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.

Page 12: Lec 31 [class design, programming by contract]

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.

Page 13: Lec 31 [class design, programming by contract]

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

Page 14: Lec 31 [class design, programming by contract]

import java.util.*;class clarity{public static void main(String args[]){LinkedList list = new LinkedList();list.add("A"); list.add("B"); list.add("C"); // ABCListIterator itr = list.listIterator(); // |ABCitr.next(); // A|BCitr.add("X"); // AX|BC // add method adds before the cursoritr.remove();itr.remove();}}/* OutputException in thread "main" java.lang.IllegalStateException at java.util.LinkedList$ListItr.remove(LinkedList.java:590) at clarity.main(clarity.java:16)*/

Page 15: Lec 31 [class design, programming by contract]

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 boolean regionMatches(int toffset, String other, int offset, int len) boollean regionMatches(boolean ignorecase , ………………..)

Consistent Pairs

InConConsistent Pairs

Page 16: Lec 31 [class design, programming by contract]

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

Page 17: Lec 31 [class design, programming by contract]

public class MessageQueue{// Instance Fieldsprivate Message[] elements; // elements stored in Message type Arrayprivate int head; // Gives head position from MessageQueueprivate int tail; // Gives tail position from MessageQueueprivate int count; // Gives count of the number of elements currently in Queue// Methodspublic MessageQueue(int capacity) { ………………} // Constructor Method// removes the First Element and returns itpublic Message removeFirst() { ……………… } // returns the First Element public Message getFirst() { ………………. }// adds a message in queuepublic void add(Message m) { ………………. }// returns the size() of the queuepublic int getSize() { ….. } { ……………….}}

Page 18: Lec 31 [class design, programming by contract]

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

Page 19: Lec 31 [class design, programming by contract]

1. Precondition for removeFirst()/**Removes message at head@return the message that has been removed from queue@precondition size() > 0*/public Message removeFirst(){}2. Precondition for add(Message) /** Appends message at tail@Param AMessage the message to be appended@precondition size() < elements.length;*/public void add(Message M){}So define a method isFull() which is public returns true or false when queue isfull or not.@precondition !isFull()

This is not valid precondition as elements is private field and can not be accessed outside.

Page 20: Lec 31 [class design, programming by contract]

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 thenAssertion Error is thrown

If condition is true execution continues.If condition false thenAssertion Error is thrown with explanation

explanationIs in the form of an String

Page 21: Lec 31 [class design, programming by contract]

Assertion cont…

• By Default Assertions are disabled in Java Interpreter

• You can enable assertions by command

java -ea <NameOfMainClass>

java –ea StudentTest

Page 22: Lec 31 [class design, programming by contract]

Exceptions in the Contract

• Assertions are new features. Before Assertions, precondition violation is dealt by throwing suitable exceptions

• Example :

public removeFirst()

{

if( count <=0 ) throw new < SomeException>

Page 23: Lec 31 [class design, programming by contract]

Exceptions cont…

• Throwing Exception in case of precondition violation has one disadvantage

“Check for Exceptions can not be turned Off”

Page 24: Lec 31 [class design, programming by contract]

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.

Page 25: Lec 31 [class design, programming by contract]

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<= head and head < elements.length

Page 26: Lec 31 [class design, programming by contract]

How to Prove Class Invariants

• To Prove an invariant you need to check

1. It is true after every constructor

2. It is true /preserved by every mutator

• No Need to check for accessor methods• Prove the invariant• Look which methods are changing the

value of head.

Page 27: Lec 31 [class design, programming by contract]

Proving Invariant

• Home Exercise ?• Second Invariant :

0 <= tail and tail < elements.length• Third Invariant : suppose we are using

ArrayLists to store Messages

elements contains only objects of type Message