CS 635 Advanced Object-Oriented Design & Programming Spring Semester, 2002 Introduction |
||
---|---|---|
© 2002, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 29-Jan-02 |
What is this Course About?
Writing quality OO code
Some basic tools:
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
Encapsulation
Enclosing all parts of an abstraction within a container
Information Hiding
Hiding parts of the abstraction
Unit Testing
Testing
Johnson's Law
If it is not tested it does not work
Types of tests
Why Unit Testing
If it is not tested it does not work
The more time between coding and testing
When to Write Unit Tests
First write the tests
Then write the code to be tested
Writing tests first saves time
Testing Catalog
Common problem areas - what to focus tests on.
Numbers
Test the boundaries of the range
for (int k = 12; k < 23; k++) { put your code here }
Strings
Test your code using the empty string
Collections
Test
Searching
Test a search that has:
When you find a bug in your code
Write a test for it
Then fix the bug
Keep track of the bugs you make
Those that do not remember history are condemned to repeat the mistakes of the past
Programmers tend to repeat the same mistakes
Keep a list of the types of mistakes you make
Write tests for them before you write code
Coupling & Cohesion
Coupling
Strength of interaction between objects in system
Cohesion
Degree to which the tasks performed by a single module are functionally related
Cohesion Linked List Example - A
public class LinkedList { void print() { String listString; lots of code to create string for the list System.out.println( listString); } }
LinkedList>>print | listString | lots of code to create string for the list Transcript show: listString; cr.
Cohesion Linked List Example - B public class LinkedList { public String toString() { String listString; lots of code to create string for the list return listString; } void print() { System.out.println( toString ); } } LinkedList>>printOn: aStream lots of code to create string for the list LinkedList>>print Transcript show: self printString; cr.
Reading Smalltalk
OOPS Rosette Stone
Java |
Smalltalk |
this
|
self |
super
|
super
|
Field
|
Instance
variable
|
Method |
Method,
message
|
"A
String"
|
'A
String'
|
/*
a comment */
|
"
a comment"
|
x
= 5;
|
x
:= 5.
|
x
== y
|
x
== y
|
x.equals(y) |
x
= y
|
if
(y > 3)
x = 12; |
y
> 3
ifTrue: [x := 12]. |
if
(y > 3)
x = 12; else x = 9; |
y
> 3
ifTrue: [x := 12] ifFalse: [x := 3]. |
z
= Point(2, 3);
|
z
:= 2 @ 3.
|
Circle
x = new Circle();
Circle y = new Circle(0, 0 3); |
|
x y |
x := Circle new. Y := Circle origin 0 @ 0 radius: 3 |
a.method() |
a
method
|
a.foo(x)
|
a
foo: x
|
a.substring(4,7) |
a
copyFrom: 4 to: 7
|
return
5;
|
^5. |
Java |
Smalltalk |
class
Circle {
public float area() { return this.radius().squared() * pi(); } } |
Circle>>area ^self radius squared * self pi |
Smalltalk Basic Rules
The Weird Stuff
Methods - No Argument
C/C++/Java |
Smalltalk |
method() |
method |
public class LinkedListExample { public static void main( String[] args ) { LinkedList list = new LinkedList(); list.print(); } }
| list | list := LinkedList new. list print.
Methods - One Argument
C/C++/Java |
Smalltalk |
method(
argument)
|
method:
argument
|
public class OneArgExample { public static void main( String[] args ) { System.out.println( "Hi mom"); } }
Transcript show: 'Hi Mom'.
Methods - Multiple Arguments
C/C++/Java |
Smalltalk |
method(arg1,
arg2, arg3)
|
method:
arg1
second: arg2 third: arg3 |
public class MultipleArgsExample { public static void main( String[] args ) { String list = "This is a sample String"; list.substring(2, 8); } }
| list | list := 'This is a sample String'. list copyFrom: 2 to: 8
Cascading Messages
Transcript show: 'Name: '; show: _name; cr; show: 'Amount: '; show: outstanding; cr.
Is short hand notation for:
Transcript show: 'Name: '. Transcript show: _name. Transcript cr. Transcript show: 'Amount: '. Transcript show: outstanding. Transcript cr.
Refactoring
We have code that looks like:
at: anInteger put: anObject (smallKey ~= largeKey) ifTrue: [(anInteger < smallKey) ifTrue: [self atLeftTree: anInteger put: anObject] ifFalse: [(smallKey = anInteger) ifTrue: [smallValue := anObject] ifFalse: [(anInteger < largeKey) ifTrue: [self atMiddleTree: anInteger put: anObject] ifFalse: [(largeKey = anInteger) ifTrue: [largeValue := anObject] ifFalse: [(largeKey < anInteger) ifTrue: [self atRightTree: anInteger put: anObject]]]]]] ifFalse:[self addNewKey: anInteger with: anObject].
Now what?
The Broken Window[1]
In inner cities some buildings are:
The Perfect Lawn
A visitor to an Irish castle asked the groundskeeper the secret of the beautiful lawn at the castle
The answer was:
Familiarity verse Comfort
Why don't more programmers/companies continually:
Refactoring
Refactoring is the modifying existing code without adding functionality
Changing existing code is dangerous
Sample Refactoring: Extract Method[2]
You have a code fragment that can be grouped together.
Turn the fragment into a method whose name explains the purpose of the method
Motivation
Short methods:
Mechanics
Mechanics - Continued
Example[3]
No Local Variables
Note I will use Fowler's convention of starting instance variables with "_".
printOwing | outstanding | outstanding := 0.0. Transcript show: '********************'; cr; show: '***Customer Owes***'; cr; show: '********************'; cr. outstanding := _orders inject: 0 into: [:sum :each | sum + each]. Transcript show: 'Name: '; show: _name; cr; show: 'Amount: '; show: outstanding; cr.
Extracting the banner code we get:
printOwing | outstanding | outstanding := 0.0. self printBanner. outstanding := _orders inject: 0 into: [:sum :each | sum + each]. Transcript show: 'Name: '; show: _name; cr; show: 'Amount: '; show: outstanding; cr.
printBanner Transcript show: '********************'; cr; show: '***Customer Owes***'; cr; show: '********************'; cr
Examples: Using Local Variables
We can extract printDetails: to get
printOwing | outstanding | self printBanner. outstanding := _orders inject: 0 into: [:sum :each | sum + each]. self printDetails: outstanding
printDetails: aNumber Transcript show: 'Name: '; show: _name; cr; show: 'Amount: '; show: aNumber; cr.
Then we can extract outstanding to get:
printOwing self printBanner; printDetails: (self outstanding)
outstanding ^_orders inject: 0 into: [:sum :each | sum + each]
The text stops here, but the code could use more work
Using Add Parameter (275)
printBanner Transcript show: '********************'; cr; show: '***Customer Owes***'; cr; show: '********************'; cr
becomes:
printBannerOn: aStream aStream show: '********************'; cr; show: '***Customer Owes***'; cr; show: '********************'; cr
Similarly we do printDetails and printOwing
printOwingOn: aStream self printBannerOn: aStream. self printDetails: (self outstanding) on: aStream
Perhaps this should be called Replace Constant with Parameter
[1] Pragmatic Programmer, pp. 4-5
[2] Refactoring Text, pp. 110-116
[3] Example code is Squeak version of Fowler's Java example
Copyright ©, All rights reserved.
2002 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.
    visitors since 29-Jan-02    Next