basic class design example: payroll purpose: picture the object-creation, message-passing interplay...

Post on 16-Dec-2015

216 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Basic Class Design

Example: Payroll

Purpose:

Picture the object-creation, message-passing interplay of objects in an executing program.

Statement of The Problem:

Given a source of time card information and a personnel file, print payroll checks

What Objects Would You Expect?

Statement of The Problem (again):

Given a source of time card information

and a personnel file, print payroll checks

Common heuristic: look for the nouns.

Payroll Classes

• PayrollMaster• Employee• PersonnelFile• TimeCard

• TimeCardFile• Check• SS#• Hours

Payroll Objects

TimeCard

getSSgetTim

e

TimeCard File

getCard

Payroll MasterDoPayroll

PersonnelFile

lookup

SSmatch

TimegetHours

Employee

PayYourself

Checkprin

t

Programmain

TimeCard File

getCard

Payroll MasterDoPayroll

Payroll MasterDoPayroll

PersonnelFile

lookup

TimeCard File

getCard

Payroll Program (1)

Programmain

Payroll MasterDoPayroll

PersonnelFile

lookup

PersonnelFile

lookup

TimeCard File

getCard

TimeCard File

getCard

Payroll MasterDoPayroll

PersonnelFile

lookup

TimeCard

getSSgetTim

e

TimeCard

getSSgetTim

e

TimeCard

getSSgetTim

e

PayrollMaster: DoPayroll (1)

TimeCard

getSSgetTim

e

TimeCard File

getCard

Payroll MasterDoPayroll

PersonnelFile

lookupget SS

SSmatchSSmatch

get SS

SSmatch

get SS

PayrollMaster: DoPayroll (2)

get SS

SSmatch

get Time

TimegetHours

get Timeget Time

TimegetHours

PayrollMaster: DoPayroll (3)

TimeCard

getSSgetTim

e

TimeCard File

getCard

Payroll MasterDoPayroll

PersonnelFile

lookup

SSmatch

get Time

TimegetHoursTimegetHoursTimegetHours

Personnel: Lookup

TimeCard

getSSgetTim

e

TimeCard File

getCard

Payroll MasterDoPayroll

PersonnelFile

lookup

SSmatch

TimegetHours

Employee

PayYourselfEmployee

PayYourselfEmployee

PayYourself

PayrollMaster: DoPayroll (4)

TimeCard

getSSgetTim

e

TimeCard File

getCard

Payroll MasterDoPayroll Personn

elFilelookup

SSmatch

TimegetHours

Employee

PayYourself

Checkprin

t

Checkprin

t

Checkprin

t

Checkprin

t

Checkprin

t

Checkprin

t

Payroll Program (2)

TimeCard

getSSgetTim

e

TimeCard File

getCard

Payroll MasterDoPayroll

PersonnelFile

lookup

SSmatch

TimegetHours

Employee

PayYourself

Checkprin

t

Programmain

A Peculiar Employee Design?

• Since when do employees create their own

checks?

• Since when are employees trusted to determine

their own pay?

(not in OUR contract!)

SMART and HELPFUL Objects

OOP and O-O Design

• Can't rush in and “program”

• Design phase needed even in simple problems– desirable in procedural programming– sine qua non in O-O world

• O-O design methodologies:– numerous– we'll consider just one simple one

Kindergarten OODStatement of

Problem

Possible Objects

Primary Object

Behavior

Interface

Sample Use

Implement

Kindergarten OOD

• Not appropriate for all problems

• Works surprisingly well on many– great for CS1

• Illustrate with an example:

Find the value of a portfolio of stocks based on “ticker-tape” information

Statement of Problem:

Find the value of a portfolio of stocksbased on "ticker-tape" information.

Possible Objects:

• Portfolio

• Holding (a portfolio item)

• Value

• TickerTape

Primary Object?

• not Holding

• not Value

• Portfolio vs. TickerTape?

Portfolio vs. TickerTape?

• Both primary in the sense of independence

• But to which object should we send a messageto solve our problem?

Is Portfolio the Primary Object?

• If so, Portfolio has this behavior:

get Value of Portfolio, given TickerTape

Is TickerTape the Primary Object?

• If so, TickerTape has this behavior:– get Value of Portfolio, given Portfolio

• Should TickerTape be responsible for computing the Value of a Portfolio?

Responsibility-Driven Design:

• objects should be responsible for themselves

• example:– objects should be responsible for their own

initialization (constructors)

• TickerTape should not be responsible for Value of a Portfolio, Portfolio should

• Primary Object:Portfolio

Behavior of Portfolio:

• get Value, given TickerTape

• constructor, given a file listing of a portfolio

Interface of Portfolio:

class Portfolio {Portfolio create()Value getValue(TickerTape t)

}

Sample Use:

create TickerTape tcreate Portfolio pto p: get Value v, given tto v: print

Implementing Portfolio:class Portfolio {

constructor() {}

Value getValue(TickerTape t) {}

}

Implementing Portfolio: getValue (1):class Portfolio {

Value getValue(TickerTape t) {for each Holding h in Collection c of Holdings {

get the Value of hincrease the total by v

}return total

}

}•Needed:

•STATE: Collection object, c

A Portfolio HAS-A collection of holdings•Local Value object, total

Implementing Portfolio: getValue (2):class Portfolio {

Value getValue(TickerTape t) {Value total initialized to 0

for each Holding h in Collection c of Holdings {get the Value of hincrease the total by v

}return total

}

STATE: Collection c}

Getting The Value of a Holding (1)

• This is OOP

• Ya want something done, send an object a

message

to h: getValue

Getting The Value of a Holding (2)to h: getValue

• Problem: a Holding is responsible for • name of stock

• number of shares

• NOT current market value

• Solution: send h an object that has the necessary behavior

to h: getValue given TickerTape t

Increasing a Value

• This is OOP

• Ya want something done, send an object a

message

to total: increase by ...

Implementing Portfolio: getValue (3):class Portfolio {

Value getValue(TickerTape t) {Value total initialized to 0for each Holding h in Collection c of Holdings {

to h: get the Value v of your stock, given tto total: increase by v

}return total

}

STATE: Collection c}

• Remark: Who initializes the Collection?

The Portfolio Constructor (1)class Portfolio {

constructor() {create Collection c... ???

}

...

STATE: Collection c

}

Constructor Questions and Answers• Questions:

– where will the portfolio data come from?– in what form will it be?

• Answers (let's say):– from a TokenSource– a sequence of (stock name and number) pairs

• Question:– Where should the responbility for creating TokenSource

lie?

The Portfolio Constructor (2)class Portfolio {

constructor(TokenSource src) {create Collection ccreate Holding h, given srcwhile h was created successfully {

to c: add hcreate Holding h, given src

}}…

STATE: Collection c}

Portfolio Class:class Portfolio {

constructor(TokenSource src) {create Collection ccreate Holding h, given srcwhile h was created successfully {

to c: add hcreate Holding h, given src

}}Value getValue(TickerTape t) {

Value total initialized to 0for each Holding h in Collection c of Holdings { to h: get the Value v of your stock, given t to total: increase by v}return total

}

STATE: Collection c}

Class Summary

Completed:– Portfolio

Yet To Complete:– TickerTape

– TokenSource

– Collection

– Holding

– Value

Details of Remaining Classes:• TickerTape— constructor• TokenSource — constructor

get String• Collection— constructor

add... some way of iterating …

• Holding— constructor, given TokenSourceget Value given TickerTape

• Value— constructor, given an integer valueincrease, given a Valueprint

NEXT STEP: Pick a class and follow same procedure…

• TickerTape

• TokenSource

• Collection

• Holding

• Value

Statement of SubProblem…

… skip steps because

behavior

interface

have been determined

Behavior of Holding:

• create, given TokenSource

• get Value given TickerTape

Interface of Holding:

class Holding {

constructor(TokenSource src)

Value getValue(TickerTape t)

}

Sample Use:

... from implementation of Portfolio

Implementing Holding:

class Holding {

constructor(TokenSource src) {}

Value getValue(TickerTape t) }}

}

Implementing Holding: getValueclass Holding {

Value getValue(TickerTape t) {to t: get Value v of stock named by my StockNameto v: multiply by my Numberreturn v

}}

• Remarks:– the object must maintain a StockName and a Number,

call them sn and n

Implementing Holding: STATE

class Holding {

Value getValue(TickerTape t) {to t: get Value v given snto v: multiply by nreturn v

}

STATE:StockName snNumber n

}

Implementing Holding: constructorclass Holding {

constructor(TokenSource src) {create StockName sn, given srccreate Number n, given src

}

...

STATE:StockName snNumber n

}

• Remark:Each class bears the responsibility for doingmost of the work to create its own instances

The Holding Classclass Holding {

constructor(TokenSource src) {create StockName sn, given srccreate Number n, given src

}

Value getValue(TickerTape t) {to t: get Value v given snto v: multiply by nreturn v

}

STATE:StockName snNumber n

}

Class Summary

Completed:– Portfolio

– Holding

Yet To Complete:– TickerTape

– TokenSource

– Collection

– Value

– Number

– StockName

Details of Remaining Classes (I):• TickerTape— constructor

– get Value given a StockName

• TokenSource — constructor– get String

• Collection— constructor– add– ... some way of iterating …

NEW!

Details of Remaining Classes (II):

• Value— constructor, given an integer value– increase, given a Value– multiply, given a Number– print

• Number— constructor

• StockName— constructor

NEW!

NEW!

NEXT STEP: Pick a class and follow procedure....

• TickerTape

• TokenSource

• Collection

• Value

• Number

• StockName

Statement of SubProblem:

• ... skip steps because behavior, interface has been determined

Behavior of TickerTape:

• Create

• get Value given StockName

Interface of TickerTape:

class TickerTape {

constructor()

TickerTape getValue(StockName sn)

}

Sample Use:

... from implementation of Holding

Implementing TickerTapeclass TickerTape {

constructor() {}

Value getValue(StockName sn) {}

}

Implementing TickerTape: getValue

Remark: need a Collection in my state

class TickerTape {

Value getValue(StockName sn) {for each StockQuote s

in my Collection c of StockQuotes {to s: does sn match?if yes {

to s: getValue vreturn v

}}error

}}

Implementing TickerTape: Stateclass TickerTape {

Value getValue(StockName sn) {for each StockQuote s

in my Collection c of StockQuotes {to s: does sn match?if yes {

to s: getValue vreturn v

}}error

}

STATE:Collection c}

Implementing TickerTape: constructorclass TickerTape {

constructor(TokenSource src) {create Collection ccreate StockQuote s given srcwhile not failure {

to c: add screate StockQuote s given src

}}

...

STATE:Collection c}

The TickerTape Classclass TickerTape {

constructor(TokenSource src) {create Collection ccreate StockQuote s given srcwhile not failure {

to c: add screate StockQuote s given src

}}

The TickerTape Class (continued)

Value getValue(StockName sn) {for each StockQuote s

in my Collection c of StockQuotes {to s: does sn match?if yes {

to s: getValue vreturn v

}}error}STATE:Collection c

}

Class Summary

Completed:– Portfolio

– Holding

– TickerTape

Yet To Complete:– TokenSource

– Collection

– Value

– Number

– StockName

– StockQuote

Details of Remaining Classes (I):• TokenSource — constructor

– get String• Collection— constructor

– add– ... some way of iterating …

• Value— constructor, given an integer value– increase, given a Value– multiply, given a Number– print

Details of Remaining Classes (II):

• Number— constructor

• StockName— constructor

• StockQuote— constructor, given a TokenSource– match a StockName– return the Value of a stock

NEW!

NEXT STEP: Pick a class and follow procedure....

• TickerTape

• TokenSource

• Collection

• Value

• Number

• StockName

• StockQuote

Statement of SubProblem:

... skip steps because behavior, interface has been determined

Behavior of StockQuote:

• create, given a TokenSource

• get Value

• is match? given a StockName

Interface of StockQuote:

class StockQuote {

constructor(TokenSource src)

Value getValue()

boolean isMatch(StockName sn)

}

Sample Use:

• ... from implementation of TickerTape

Implementing StockQuote

class StockQuote {constructor(TokenSource src) {

}

StockQuote getValue() {

}

boolean isMatch(StockName sn) {

}

}

Implementing StockQuote (I)class StockQuote {

constructor(TokenSource src) {}

StockQuote getValue() {return v;

}

boolean isMatch(StockName sn) {to sn: does my StockName sn match?if yes return true else return false

}

STATE:Value vStockName sn

}

Implementing StockQuote (II)class StockQuote {

constructor(TokenSource src) {create StockName sn, given srccreate Value v, given src

}

...

STATE:Value vStockName sn

}

The StockQuote Classclass StockQuote {

constructor(TokenSource src) {create StockName sn, given srccreate Value v, given src

}

StockQuote getValue() {return v;

}

boolean isMatch(StockName sn) {to sn: does my StockName sn match?if yes return true else return false

}

STATE:Value vStockName sn

}

Class Summary

Completed:– Portfolio

– Holding

– TickerTape

– StockQuote

Yet To Complete:– TokenSource

– Collection

– Value

– Number

– StockName

Details of Remaining Classes (I):• TokenSource — constructor

– get String• Collection— constructor

– add– ... some way of iterating …

• Value— constructor, given an integer value– increase, given a Value– multiply, given a Number– print

Details of Remaining Classes (II):

• Number— constructor

• StockName— constructor– is Match? given another StockName

NEW!

NEXT STEP: Pick a class and follow procedure....

• TickerTape

• TokenSource

• Collection

• Value

• Number

• StockName

Statement of SubProblem:

• ... skip steps because behavior, interface has been determined

Behavior of Value:

• create, given a TokenSource

• increase, given a Value

• multiply, given a Number

• print

Interface of Value:

class Value {

Value create(TokenSource src)

void increase(Value v)

void multiply(Number n)

void print()

}

Sample Use:

... from implementation of TickerTape

Implementing Value

class Value {

Value create(TokenSource src) {

}

void increase(Value v) {

}

void multiply(Number n) {

}

void print() {

}

}

Implementing Value: constructor

class Value {constructor(TokenSource src) {

to src: get String integerPartto src: get String fractionto fraction: contains / ?if no

to src: put back String fraction// just use integerPart

else// use integerPart and fraction

}...

}

Implementing Value: other methodsclass Value {

Value create(TokenSource src) {...

}

void increase(Value v) {// defer

}

void multiply(Number n) {// defer

}

void print() {// defer

}

STATE: ???}

Class Summary

Completed:– Portfolio

– Holding

– TickerTape

– StockQuote

– Value (partially)

Yet To Complete:– TokenSource

– Collection

– Number

– StockName

Details of Remaining Classes:• TokenSource — constructor

– get String– put back String, given String

• Collection— constructor– add– ... some way of iterating …

• Number— constructor

• StockName— constructor– is Match? given another StockName

NEW!

NEXT STEP:

And so on …

(I'm tired now— aren't you?)

top related