CS 535 Object-Oriented Programming & Design Spring Semester, 1999 Basic Heuristics |
||
---|---|---|
© 1999, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 16-Feb-99 |
The Basic Heuristics
2.1 All data should be hidden within its class
3.3 Beware of classes that have many accessor methods defined in their public interfaces. Having many implies that related data and behavior are not being kept in one place
2.9 Keep related data and behavior in one place
2.8 A class should capture one and only one key abstraction
3.1 Distribute system intelligence horizontally as uniformly as possible
3.2 Do not create god classes/objects in your systems
Example 1 - Stack
Definition
Stack Class The following Stack class is not a production level class.
class Stack { private float[] elements; private int topOfStack = -1; public Stack( int stackSize ) { elements = new float[ stackSize ]; } public void push( float item ) { elements[ ++topOfStack ] = item; } public float pop() { return elements[ topOfStack-- ]; } public boolean isEmpty() { if ( topOfStack < 0 ) return true; else return false; } public boolean isFull() { if ( topOfStack >= elements.length ) return true; else return false; } }
Using the Stack Stack me = new Stack( 20 ); me.push( 5 ); me.push( 12 ); System.out.println( me.pop() ); System.out.println( me.pop() );
Some Typical Beginner Mistakes
Struct-like Class
One can make a class that is just a struct dressed as a class. Remember heuristic 2.1 All data should be hidden within its class.
class StackData { public float[] elements = new float[100]; public int topOfStack = 0; } class Test { static void push(Stack it, int item) { it.stack[ ( it.topOfStack )++ ] = item; } static float pop(Stack it) { return it.stack[--(it.topOfStack)]; } public void static main( String[] args) { Stack yours, mine; push( yours, 3.3 ); push( mine, 9.9); }
Some Typical Beginner MistakesThe Long Way Struct-like Class
This example has all fields hidden. But the methods do not support the stack abstraction. The logic of operating the stack is not in the stack class. This means that the topOfStack field can be improperly set by some one outside the class. Remember heuristic 3.3 Beware of classes that have many accessor methods defined in their public interfaces. Having many implies that related data and behavior are not being kept in one place.
class StackData { private float[] elements = new float[100]; private int topOfStack = -1; public int getTopOfStack() { return topOfStack; } public void setTopOfStack( int newTop ) { topOfStack = newTop; } public float getElement( int elementIndex ) { return elements[ elementIndex ]; } public void setElement( int elementIndex, float element ) { elements[ elementIndex ] = element; } }
Information Hiding - Physical and Logical
Physical Information Hiding
Physical information hiding is when a class has a field and there are accessor methods, getX and setX, setting and getting the value of the field. It is clear to everyone that there is a field named X in the class. The goal is just to prevent any direct access to X from the outside. The extreme example is a struct converted to a class by adding accessor methods. Physical information hiding provides little or no help in isolating the effects of changes. If the hidden field changes type than one usually ends up changing the accessor methods to reflect the change in type.
Logical Information Hiding
Logical information hiding occurs when the class represents some abstraction. This abstraction can be manipulated independent of its underlying representation. Details are being hidden from the out side world. Examples are integers and stacks. We use integers all the time without knowing any detail on their implementation. Similarly we can use the operations pop and push without knowing how the stack is implemented.
Example 2 - Linked List
What operations do we want on a linked-list?
struct Node { float data; struct Node* next; };
First Java Linked List
package MyLinkedList; public class LinkedList { private Node frontOfList = null; public void addFirst( float data ) { Node newNode = new Node(); newNode.data = data; newNode.next = frontOfList; frontOfList = newNode; } public String toString() { String listAsString = ""; Node current = frontOfList; while (current != null ) { listAsString = listAsString + " " + current.data; current = current.next; } return listAsString; } // Other methods deleted } class Node { float data; Node next = null; }
Using the First Linked List
import MyLinkedList; public class Test { public static void main( String args[] ) throws Exception { //new ClassMethodView( Test.class ); LinkedList test = new LinkedList(); test.addFirst( 1); test.addFirst( 2); test.addFirst( 3); System.out.println( test ); } }Output 3.0 2.0 1.0What is Wrong with the Node Class?
Clearly the Node class does what an earlier slide says not to do. So what? Most textbooks will have Node code that looks like the first example. The Java library source code has many instances of linked lists that use this type of Node class. So what is wrong with Node class? Put another way how can it be improved?.
Think about this before going on to the next slide.
Second Node Class
class Node { private float data; private Node next = null; private Node previous = null; public Node( float initialData) { this( initialData, null, null ); } public Node( float initialData, Node previousInList, Node nextInList ) { data = initialData; next = nextInList; previous = previousInList; if ( next != null ) next.previous = this; if ( previous != null ) previous.next = this; } public void append( float data ) { new Node( data, this, next); } public void prepend( float data ) { new Node( data, previous, this); }
// Node Continued
public void remove() { if ( previous != null ) previous.next = next; if ( next != null ) next.previous = previous; previous = null; next = null; } public Node getNext() { return next; } public Node getPrevious() { return previous; } public float getData() { return data; } public void setData( float newData ) { data = newData; } }
Second Linked List public class LinkedList { private Node frontOfList = null; private Node endOfList = null; public void addFirst( float data ) { frontOfList = new Node( data, null, frontOfList ); if (endOfList == null ) endOfList = frontOfList; } public void addLast( float data ) { endOfList = new Node( data, endOfList, null ); if (frontOfList == null ) frontOfList = endOfList; } public float removeFirst( ) { Node oldFirst = frontOfList; frontOfList = frontOfList.getNext(); oldFirst.remove(); return oldFirst.getData(); } public String toString() { String listAsString = ""; Node current = frontOfList; while (current != null ) { listAsString = listAsString + " " + current.getData(); current = current.getNext(); } return listAsString; } }
Is the Second List Better?
What is the difference between the first and second Node classes?
Is the second Node better? If so how?
Computation as Simulation Procedure programming consists of procedures acting on data
Object-oriented programming consists of objects interacting
Main() creates web of objects and starts them interacting
Copyright © 1999 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
All rights reserved.
Previous    visitors since 16-Feb-99    Next