CS 535 Object-Oriented Programming Fall Semester, 2003 Some OO Terms |
||
---|---|---|
© 2003, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 14-Oct-03 |
Some OO Terms
Abstraction
“Extracting the essential details about an item or group of items, while ignoring the unessential details.”
Edward Berard
“The process of identifying common patterns that have systematic variations; an abstraction represents the common pattern and provides a means for specifying which variation to use.”
Richard Gabriel
Example
Pattern: Priority queue Essential Details: length items in queue operations to add/remove/find item Variation: link list vs. array implementation stack, queue
Heuristic 2.8
A class should capture one and only one key abstraction
Look at nouns in requirements specification or system description
Look at these phrases. Some will be obvious classes, some will be obvious nonsense, and some will fall between obvious and nonsense. Skip the nonsense, keep the rest. The goal is a list of candidate objects. Some items in the list will be eliminated, others will be added later. Finding good objects is a skill, like finding a good functional decomposition.
A refrigerator has a motor, a temperature sensor, a light and a door. The motor turns on and off primarily as prescribed by the temperature sensor. However, the motor stops when the door is opened. The motor restarts when the door is closed if the temperature is too high. The light is turned on when the door opens and is turned off when the door is closed.
Encapsulation
Enclosing all parts of an abstraction within a container
Class contains
(aPoint x squared + aPoint y squared) sqrt
aPoint r
Information Hiding
An object should hide design decisions from its users
Hide
Heuristic 2.1
All data should be hidden within it class
Smalltalk instance variables in can be accessed in:
Hiding Instance Variables
Some argue that only two methods should access an instance variable
Class BankAccount Instance variable: balance
balance ^balance
balance: aNumber balance := anumber
deposit: aNumber self balance: (self balance + aNumber)
This protects the class from changes in instance variables
balance: aNumber aNumber < 0 ifTrue: [ NegativeBalanceError raiseSignal]. balance := aNumber
Hiding Instance Variables & Refactoring Browser
Refactoring browser
Smalltalk and Private Methods
Private method
Engineering Heuristics, Absolutes & Beginners
All design decisions involve trade offs
Heuristics are design decisions that are nearly always true
No heuristic is correct all the time
Beginners violate heuristics because
Two View of a Class: Inside & Outside
Users of a class care about
Inheritance (White Box) Verses Composition (Black Box)
Composition
Smalltalk defineClass: #ComposedWordSteam superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: 'input ' classInstanceVariableNames: '' imports: '' category: 'CS535'
Class Methods
on: aCollection ^self input: (ReadStream on: aCollection)
input: aStream ^super new setInput: aStream
Instance Methods
atEnd ^input atEnd
next "some code to get the next word" blah
peek ^input peek
setInput: aStream input :=aStream
Inheritance
Smalltalk.Core defineClass: #WordStream superclass: #{Core.ReadStream} indexedType: #none private: false instanceVariableNames: '' classInstanceVariableNames: '' imports: '' category: 'CS535'
next "some code to get the next word" blah
But what if we don’t want peek changed?
Inheritance (White Box) Verses Composition (Black Box)
Inheritance
Need to know how super class works
Hard to change super class
May inherit methods you don’t want
Can replace uses of super class (ReadStream) with new class (WordStream)
Composition
Don’t need to know how composed object (ReadStream) works
Can change type of composed object
Controls which methods of composed object to expose
Forward messages to composed object
In languages that declare types may not be able to replace composed object with new class (WordStream)
Coupling
Strength of interaction between objects in system
How tangled together the classes are
Cohesion
Degree to which the tasks performed by a single module are functionally related
Ralph Johnson’s Suggestions for Finding Abstractions
Do One Thing
Method should do on thing
findString:startingAt: asNumber asUppercase dropFinalVowels
String OrderedCollection Array ReadStream
Eliminate Duplication
(self asInteger - $a asInteger + anInteger) \\ 26 – (self asInteger - $a asInteger)
(self alphabetValue + anInteger) \\ 26 - self alphabetValue.
Keep rate of change similar
Minimize interfaces
Use the smallest interface you can
Minimize size of abstractions
Methods should be small
|
Average |
Mean |
Variables
/ class
|
2.1 |
1 |
Methods
/ class
|
16.7 |
9 |
Carriage
returns/method
|
7.6 |
5.0 |
Code used to generate Numbers
Variables Per Class
classes :=Smalltalk allClasses reject: [:each | each isMeta] variablesInClass :=classes collect: [:each | each instVarNames size]. average :=((variablesInClass fold: [:sum :each | sum + each] )/ variablesInClass size) asFloat. mean := variablesInClass asSortedCollection at: variablesInClass size // 2. max := variablesInClass fold: [:partialMax :each | partialMax max: each]
Methods Per Class
classes :=Smalltalk allClasses reject: [:each | each isMeta] methodsInClass :=classes collect: [:each | each selectors size]. average :=((methodsInClass fold: [:sum :each | sum + each] )/ methodsInClass size) asFloat. mean := methodsInClass asSortedCollection at: methodsInClass size // 2. max := methodsInClass fold: [:partialMax :each | partialMax max: each]
Minimize number of abstractions
A class hierarchy 6-7 levels deep is hard to learn
Break large system into subsystems, so people only have to learn part of the system at a time
Polymorphism
Example
Counter>>printOn: aStream aStream nextPutAll: ‘Counter(‘; nextPutAll: count printString; nextPutAll: ‘)’
aStream can be any object that implements nextPutAll:
Note we do not write:
Counter>>printOn: aStream aStream class = FileStream ifTrue:[ write to file ]. aStream class = WriteStream ifTrue: [write to write stream] aStream class = TextCollector ifTrue: [write to Transcript]
Avoid Case Statements
Smalltalk has no case statement
OO programers send a message to object instead
Each type of object handles the message according to its type
Case statements make it harder to add new cases
Simplistic Example
Bank offers various types of accounts:
Banking Classes
Customer
Transaction
Currency
Processing a Transaction
Using Case Statment
newCustomer := Bank createNewAccount: type.
Etc.
newCustomer class = Checking ifTrue:[ ...]
newCustomer class = Savings ifTrue:[ ...]
newCustomer class = CD ifTrue:[ ...]
newCustomer class = Jonior ifTrue:[ ...]
Polymorphism
newCustomer := Bank createNewAccount: type.
newCustomer.processTransaction: amount
Which processTransaction is called?
Adding new types of accounts to program requires:
Linked List Example
Note all the checking at in the methods
Smalltalk defineClass: #LinkedList superclass: #{Core.SequenceableCollection} indexedType: #none private: false instanceVariableNames: 'value next ' classInstanceVariableNames: '' imports: '' category: 'CS535'
Class Methods
with: anObject ^super new setValue: anObject
Instance Methods
addLast: anObject next ifNotNil: [^next addLast: anObject]. next := LinkedList with: anObject.
includes: anObject value = anObject ifTrue:[^true]. next ifNotNil: [^next includes: anObject]. ^false
printOn: aStream aStream print: value; nextPutAll: ' '. next ifNotNil: [next printOn: aStream]
setValue: anObject value := anObject.
size next ifNil: [^1]. ^next size + 1
LinkedList with Poymorphism
A node to represent the end of the list
Smalltalk defineClass: #NilNode superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: '' classInstanceVariableNames: '' imports: '' category: 'CS535'Instance Methods addLast: anObject self become: (LinkedList with: anObject)
includes: anObject ^false
printOn: aStream
size ^0
LinkedList with NilNode
Smalltalk defineClass: #LinkedList superclass: #{Core.SequenceableCollection} indexedType: #none private: false instanceVariableNames: 'value next ' classInstanceVariableNames: '' imports: '' category: 'CS535'Class Methods with: anObject ^super new setValue: anObjectInstance Methods addLast: anObject next addLast: anObject
includes: anObject value = anObject ifTrue:[^true]. ^next includes: anObject
printOn: aStream aStream print: value; nextPutAll: ' '. next printOn: aStream
setValue: anObject value := anObject. next := NilNode new.
size ^next size + 1
Copyright ©, All rights reserved.
2003 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.
Previous    visitors since 14-Oct-03    Next