SDSU CS 535 Object-Oriented Programming & Design
Fall Semester, 2001
Two Questions
Previous    Lecture Notes Index    Next    
© 2001, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 06-Dec-01

Contents of Doc 23, Two Questions


References

Refactoring: Improving the Design of Existing Code, Fowler, Addison-Wesley, 1999


Doc 23, Two Questions Slide # 2

Question 11


Q11. In my employee class there are many instance variable like ID, name address phone number...? What is the best way to organize it? should I divide it into subclass?

Smalltalk.CS535 defineClass: #Customer
   superclass: #{UI.ApplicationModel}
   indexedType: #none
   private: false
   instanceVariableNames: 'firstName lastName middleName homePhoneNumber workPhoneNumber cellPhoneNumber streetAddress city state zipCode id '
   classInstanceVariableNames: ''
   imports: ''
   category: 'Course-GUI-Examples'
Class Methods

firstName: aFirstNameString middleName: aMiddleNameString lastName: aLastNameString homePhoneNumber: aHomePhoneNumberString workPhoneNumber: aWorkPhoneNumberString cellPhoneNumber: aCellPhoneNumberString streetAddress: aStreetAddressString city: aCityString state: aStateString zipCode: aZipCodeString id: aNumber
   ^super new
      firstName: aFirstNameString;
      middleName: aMiddleNameString; 
      lastName: aLastNameString;
      homePhoneNumber: aHomePhoneNumberString;
      workPhoneNumber: aWorkPhoneNumberString; 
      cellPhoneNumber: aCellPhoneNumberString; 
      streetAddress: aStreetAddressString;
      city: aCityString;
      state: aStateString; 
      zipCode: aZipCodeString;
      id: aNumber

Doc 23, Two Questions Slide # 3
Instance Methods
city
   ^city
city: aString
   city:= aString
firstName
   ^firstName
firstName: aString
   firstName:= aString
id
   ^id
id: anInteger
   id := anInteger.
lastName
   ^lastName
lastName: aString 
   lastName := aString
middleName
   ^middleName
middleName: aString 
   middleName := aString
streetAddress
   ^streetAddress
streetAddress: aString
   streetAddress:= aString 
etc.

Doc 23, Two Questions Slide # 4

So what are the Problems?



Doc 23, Two Questions Slide # 5
So what are the Solutions?


Doc 23, Two Questions Slide # 6

Code Smells


If it stinks, change it

-- Grandma Beck on child-rearing


Some Smells

Long Parameter List

Data Class
A class with instance variable, setter and getter methods and nothing else


Doc 23, Two Questions Slide # 7
Some Classes

Address
Name
PhoneNumber

It is clear what the instance variable would be

What are the responsibilities of each class?


Doc 23, Two Questions Slide # 8
Name

Knowing when two names are equal
Knowing the full name
Knowing the short name
Knowing when two names might be equal
One name mispelled
One name with an abbreviation
Roger Whitney
Roger E Whitney
Roger Earl Whitney
Displaying self in a Window

Serialize/deserialize it to/from an ASCII string

Doc 23, Two Questions Slide # 9
Phone Number

Know the number
Know type of phone number
Cell phone
Work
Home
Beeper

Format the number

Know if it is local or long distance

Serialize/deserialize it to/from an ASCII string

Doc 23, Two Questions Slide # 10
Start of a Name Class

Smalltalk.CS535 defineClass: #Name
   superclass: #{Core.Object}
   indexedType: #none
   private: false
   instanceVariableNames: 'title first middle last '
   classInstanceVariableNames: ''
   imports: ''
   category: 'Course-GUI-Examples'

CS535.Name class methodsFor: 'Instance Creation'

title: titleString first: firstNameString middle: middleNameString last: lastNameString 
   ^super new
      setTitle: titleString
      setFirst: firstNameString
      setMiddle: middleNameString
      setLast: lastNameString 

CS535.Name methodsFor: 'accessing'

fullName
   | name |
   name := String new writeStream.
   title isNil ifFalse: [name nextPutAll: title , ' '].
   name nextPutAll: first , ' '.   
   middle isNil ifFalse: [name nextPutAll: middle , ' '].   
   name nextPutAll: last.   
   ^name contents

Doc 23, Two Questions Slide # 11

shortName
   ^title isNil
      ifTrue:[first , ' ' , last]
      ifFalse:[title , ' ' , last] 

CS535.Name methodsFor: 'initialize'

setTitle: titleString 
   titleString isNil ifTrue:[^nil].
   titleString isEmpty ifTrue:[^nil].
   titleString size > 3 ifTrue:[^title := titleString].
   title := titleString last = $.
      ifTrue:[titleString]
      ifFalse:[titleString , (String with: $.)]

setTitle: titleString setFirst: firstString setMiddle: middleString setLast: lastString 
   self setTitle: titleString.
   first := firstString.
   middle := middleString.
   last := lastString 

CS535.Name methodsFor: 'comparing'

= aName
   ^self fullName = aName fullName 

Doc 23, Two Questions Slide # 12
Customer Class Becomes

Smalltalk.CS535 defineClass: #Customer
   superclass: #{UI.ApplicationModel}
   indexedType: #none
   private: false
   instanceVariableNames: 'name phoneNumber address id '
   classInstanceVariableNames: ''
   imports: ''
   category: 'Course-GUI-Examples'
Class Methods

name: aName address: anAddress id: id
   ^super new
      setName: aName
      setAddress: aNumber
      setId: id


Doc 23, Two Questions Slide # 13
Question 12

If one of my methods maybe in my video class is simply '^ videoID', what is the simplest way for the GUI to use that?

There are a number of ways depending on:



Doc 23, Two Questions Slide # 14

GUI & Program read/writes values at the same time


There are two options when



Doc 23, Two Questions Slide # 15

Option 1 - Use Value Holder


We can

Smalltalk.CS535 defineClass: #Video
   superclass: #{UI.ApplicationModel}
   indexedType: #none
   private: false
   instanceVariableNames: 'id '
   classInstanceVariableNames: ''
   imports: ''
   category: 'Course-GUI-Examples'

id
   ^self idHolder value

idHolder
   ^id isNil
      ifTrue:
         [id := String new asValue]
      ifFalse:
         [id] 


Doc 23, Two Questions Slide # 16

Option 2 - Use Adapter



Smalltalk.CS535 defineClass: #Video
   superclass: #{UI.ApplicationModel}
   indexedType: #none
   private: false
   instanceVariableNames: 'id '
   classInstanceVariableNames: ''
   imports: ''
   category: 'Course-GUI-Examples'

id: aNumber
id := aNumber.
self changed: #id

id
   ^id

idHolder
| adaptor |
adaptor := AspectAdaptor forAspect: #id.
adaptor
subject: self;
subjectSendsUpdates: true.
^adaptor


Doc 23, Two Questions Slide # 17

Program doesn't change the value while GUI is displayed


In this case option 1 & 2 still work, but we another option

Option 3 - Use Adapter no broadcast



Smalltalk.CS535 defineClass: #Video
   superclass: #{UI.ApplicationModel}
   indexedType: #none
   private: false
   instanceVariableNames: 'id '
   classInstanceVariableNames: ''
   imports: ''
   category: 'Course-GUI-Examples'

id: aNumber
id := aNumber.

id
   ^id

idHolder
| adaptor |
adaptor := AspectAdaptor forAspect: #id.
adaptor subject: self;
^adaptor


Doc 23, Two Questions Slide # 18

GUI is read-only

Program doesn't change value when GUI displayed

Options 1-3 work but we have option 4 & 5

Option 4 - No setter method with adaptor


Smalltalk.CS535 defineClass: #Video
   superclass: #{UI.ApplicationModel}
   indexedType: #none
   private: false
   instanceVariableNames: 'id '
   classInstanceVariableNames: ''
   imports: ''
   category: 'Course-GUI-Examples'

id
   ^id

idHolder
| adaptor |
adaptor := AspectAdaptor forAspect: #id.
adaptor subject: self;
^adaptor


Doc 23, Two Questions Slide # 19

Option 5 - No setter method with ValueHolder


Smalltalk.CS535 defineClass: #Video
   superclass: #{UI.ApplicationModel}
   indexedType: #none
   private: false
   instanceVariableNames: 'id '
   classInstanceVariableNames: ''
   imports: ''
   category: 'Course-GUI-Examples'

id
   ^id

idHolder
   ^self id asValue


Doc 23, Two Questions Slide # 20
Comments on Option 4 & 5

The original questioner

Option 4 & 5 require


Doc 23, Two Questions Slide # 21
For those Who like to live Dangerously

No accessors needed

Smalltalk.CS535 defineClass: #Video
   superclass: #{UI.ApplicationModel}
   indexedType: #none
   private: false
   instanceVariableNames: 'id '
   classInstanceVariableNames: ''
   imports: ''
   category: 'Course-GUI-Examples'

idHolder
   |adaptor idIndex |
   idIndex := self class allInstVarNames indexOf: 'id'.
   adaptor := SlotAdaptor forIndex: idIndex.
   adaptor subject: self.
   ^adaptor
SlotAdaptor will set/get values of instance variable without needing accessor methods

Code above breaks if change the name of the instance variable

Copyright ©, All rights reserved.
2000 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.

Previous    visitors since 06-Dec-01    Next