Basic Class Design Example Payroll Purpose Picture the

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 • • Payroll. Master Employee Personnel. File Time. Card • • Time. Card. File Check SS# Hours

Payroll Objects Program main Personnel File lookup Payroll Master Do. Payroll Time. Card File Time get. Card get. Hours Pay. Yourself Time. Card Employee get. Time get. SS Check print SS match

Payroll Program (1) Program main Personnel File lookup Time. Card File get. Card Payroll Master Do. Payroll

Payroll. Master: Do. Payroll (1) Payroll Master Do. Payroll Personnel File Time. Card File lookup get. Card Time. Card get. Time get. SS

Payroll. Master: Do. Payroll (2) Payroll Master Do. Payroll Personnel File Time. Card File get SS lookup get. Card SS SS Time. Card get. Time get. SS match

Payroll. Master: Do. Payroll (3) Payroll Master Do. Payroll Personnel File Time. Card File lookup get Time get. Card Time get. Hours Time. Card get. Time get. SS SS match

Personnel: Lookup Payroll Master Do. Payroll Personnel File Time. Card File lookup get. Card Pay. Yourself Employee Time get. Hours Time. Card get. Time get. SS SS match

Payroll. Master: Do. Payroll (4) Payroll Master Do. Payroll Personnel File lookup Time. Card File get. Card Time get. Hours Pay. Yourself Employee Time. Card get. Time get. SS Check print SS match

Payroll Program (2) Program main Personnel File lookup Payroll Master Do. Payroll Time. Card File Time get. Card get. Hours Pay. Yourself Time. Card Employee get. Time get. SS Check print SS match

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 OOD Statement 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 CS 1 • 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 stocks based on "ticker-tape" information.

Possible Objects: • • Portfolio Holding (a portfolio item) Value Ticker. Tape

Primary Object? • not Holding • not Value • Portfolio vs. Ticker. Tape?

Portfolio vs. Ticker. Tape? • Both primary in the sense of independence • But to which object should we send a message to solve our problem?

Is Portfolio the Primary Object? • If so, Portfolio has this behavior: get Value of Portfolio, given Ticker. Tape

Is Ticker. Tape the Primary Object? • If so, Ticker. Tape has this behavior: – get Value of Portfolio, given Portfolio • Should Ticker. Tape 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) • Ticker. Tape should not be responsible for Value of a Portfolio, Portfolio should • Primary Object: Portfolio

Behavior of Portfolio: • get Value, given Ticker. Tape • constructor, given a file listing of a portfolio

Interface of Portfolio: class Portfolio { Portfolio create() Value get. Value(Ticker. Tape t) }

Sample Use: create Ticker. Tape t create Portfolio p to p: get Value v, given t to v: print

Implementing Portfolio: class Portfolio { constructor() { } Value get. Value(Ticker. Tape t) { } }

Implementing Portfolio: get. Value (1): class Portfolio { Value get. Value(Ticker. Tape t) { for each Holding h in Collection c of Holdings { get the Value of h increase the total by v } return total } } • Needed: • STATE: Collection object, c A Portfolio HAS-A collection of holdings • Local Value object, total

Implementing Portfolio: get. Value (2): class Portfolio { Value get. Value(Ticker. Tape t) { Value total initialized to 0 for each Holding h in Collection c of Holdings { get the Value of h increase 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: get. Value

Getting The Value of a Holding (2) to h: get. Value • 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: get. Value given Ticker. Tape t

Increasing a Value • This is OOP • Ya want something done, send an object a message to total: increase by. . .

Implementing Portfolio: get. Value (3): class Portfolio { Value get. Value(Ticker. Tape t) { Value total initialized to 0 for 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 } • 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 Token. Source – a sequence of (stock name and number) pairs • Question: – Where should the responbility for creating Token. Source lie?

The Portfolio Constructor (2) class Portfolio { constructor(Token. Source src) { create Collection c create Holding h, given src while h was created successfully { to c: add h create Holding h, given src } } … STATE: Collection c }

Portfolio Class: class Portfolio { constructor(Token. Source src) { create Collection c create Holding h, given src while h was created successfully { to c: add h create Holding h, given src } } Value get. Value(Ticker. Tape t) { Value total initialized to 0 for 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: – – – Ticker. Tape Token. Source Collection Holding Value

Details of Remaining Classes: • Ticker. Tape— constructor • Token. Source — constructor get String • Collection— constructor add. . . some way of iterating … • Holding— constructor, given Token. Source get Value given Ticker. Tape • Value— constructor, given an integer value increase, given a Value print

NEXT STEP: Pick a class and follow same procedure… • • • Ticker. Tape Token. Source Collection Holding Value

Statement of Sub. Problem… … skip steps because behavior interface have been determined

Behavior of Holding: • create, given Token. Source • get Value given Ticker. Tape

Interface of Holding: class Holding { constructor(Token. Source src) Value get. Value(Ticker. Tape t) }

Sample Use: . . . from implementation of Portfolio

Implementing Holding: class Holding { constructor(Token. Source src) { } Value get. Value(Ticker. Tape t) } } }

Implementing Holding: get. Value class Holding { Value get. Value(Ticker. Tape t) { to t: get Value v of stock named by my Stock. Name to v: multiply by my Number return v } } • Remarks: – the object must maintain a Stock. Name and a Number, call them sn and n

Implementing Holding: STATE class Holding { Value get. Value(Ticker. Tape t) { to t: get Value v given sn to v: multiply by n return v } STATE: } Stock. Name sn Number n

Implementing Holding: constructor class Holding { constructor(Token. Source src) { create Stock. Name sn, given src create Number n, given src }. . . STATE: Stock. Name sn Number n } • Remark: Each class bears the responsibility for doing most of the work to create its own instances

The Holding Class class Holding { constructor(Token. Source src) { create Stock. Name sn, given src create Number n, given src } Value get. Value(Ticker. Tape t) { to t: get Value v given sn to v: multiply by n return v } STATE: } Stock. Name sn Number n

Class Summary Completed: – Portfolio – Holding Yet To Complete: – – – Ticker. Tape Token. Source Collection Value Number Stock. Name

Details of Remaining Classes (I): • Ticker. Tape— constructor – get Value given a Stock. Name • Token. Source — 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 • Stock. Name— constructor NEW !

NEXT STEP: Pick a class and follow procedure. . • • • Ticker. Tape Token. Source Collection Value Number Stock. Name

Statement of Sub. Problem: • . . . skip steps because behavior, interface has been determined

Behavior of Ticker. Tape: • Create • get Value given Stock. Name

Interface of Ticker. Tape: class Ticker. Tape { constructor() Ticker. Tape get. Value(Stock. Name sn) }

Sample Use: . . . from implementation of Holding

Implementing Ticker. Tape class Ticker. Tape { constructor() { } Value get. Value(Stock. Name sn) { } }

Implementing Ticker. Tape: get. Value class Ticker. Tape { Value get. Value(Stock. Name sn) { for each Stock. Quote s in my Collection c of Stock. Quotes { to s: does sn match? if yes { to s: get. Value v return v } } error } } Remark: need a Collection in my state

Implementing Ticker. Tape: State class Ticker. Tape { Value get. Value(Stock. Name sn) { for each Stock. Quote s in my Collection c of Stock. Quotes { to s: does sn match? if yes { to s: get. Value v return v } } error } STATE: } Collection c

Implementing Ticker. Tape: constructor class Ticker. Tape { constructor(Token. Source src) { create Collection c create Stock. Quote s given src while not failure { to c: add s create Stock. Quote s given src } }. . . STATE: } Collection c

The Ticker. Tape Class class Ticker. Tape { constructor(Token. Source src) { create Collection c create Stock. Quote s given src while not failure { to c: add s create Stock. Quote s given src } }

The Ticker. Tape Class (continued) Value get. Value(Stock. Name sn) { for each Stock. Quote s in my Collection c of Stock. Quotes { to s: does sn match? if yes { to s: get. Value v return v } } error } STATE: Collection c }

Class Summary Completed: – Portfolio – Holding – Ticker. Tape Yet To Complete: – – – Token. Source Collection Value Number Stock. Name Stock. Quote

Details of Remaining Classes (I): • Token. Source — 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 NEW • Stock. Name— constructor ! • Stock. Quote— constructor, given a Token. Source – match a Stock. Name – return the Value of a stock

NEXT STEP: Pick a class and follow procedure. . • • Ticker. Tape Token. Source Collection Value Number Stock. Name Stock. Quote

Statement of Sub. Problem: . . . skip steps because behavior, interface has been determined

Behavior of Stock. Quote: • create, given a Token. Source • get Value • is match? given a Stock. Name

Interface of Stock. Quote: class Stock. Quote { constructor(Token. Source src) Value get. Value() boolean is. Match(Stock. Name sn) }

Sample Use: • . . . from implementation of Ticker. Tape

Implementing Stock. Quote class Stock. Quote { constructor(Token. Source src) { } Stock. Quote get. Value() { } boolean is. Match(Stock. Name sn) { } }

Implementing Stock. Quote (I) class Stock. Quote { constructor(Token. Source src) { } Stock. Quote get. Value() { return v; } boolean is. Match(Stock. Name sn) { to sn: does my Stock. Name sn match? if yes return true else return false } STATE: } Value v Stock. Name sn

Implementing Stock. Quote (II) class Stock. Quote { constructor(Token. Source src) { create Stock. Name sn, given src create Value v, given src }. . . STATE: } Value v Stock. Name sn

The Stock. Quote Class class Stock. Quote { constructor(Token. Source src) { create Stock. Name sn, given src create Value v, given src } Stock. Quote get. Value() { return v; } boolean is. Match(Stock. Name sn) { to sn: does my Stock. Name sn match? if yes return true else return false } STATE: } Value v Stock. Name sn

Class Summary Completed: – – Portfolio Holding Ticker. Tape Stock. Quote Yet To Complete: – – – Token. Source Collection Value Number Stock. Name

Details of Remaining Classes (I): • Token. Source — 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 • Stock. Name— constructor NEW – is Match? given another Stock. Name !

NEXT STEP: Pick a class and follow procedure. . • • • Ticker. Tape Token. Source Collection Value Number Stock. Name

Statement of Sub. Problem: • . . . skip steps because behavior, interface has been determined

Behavior of Value: • • create, given a Token. Source increase, given a Value multiply, given a Number print

Interface of Value: class Value { Value create(Token. Source src) void increase(Value v) void multiply(Number n) void print() }

Sample Use: . . . from implementation of Ticker. Tape

Implementing Value class Value { Value create(Token. Source src) { } void increase(Value v) { } void multiply(Number n) { } void print() { } }

Implementing Value: constructor class Value { constructor(Token. Source src) { to src: get String integer. Part to src: get String fraction to fraction: contains / ? if no to src: put back String fraction // just use integer. Part else // use integer. Part and fraction }. . . }

Implementing Value: other methods class Value { Value create(Token. Source src) {. . . } void increase(Value v) { // defer } void multiply(Number n) { // defer } void print() { // defer } STATE: ? ? ? }

Class Summary Completed: – – – Portfolio Holding Ticker. Tape Stock. Quote Value (partially) Yet To Complete: – – Token. Source Collection Number Stock. Name

Details of Remaining Classes: • Token. Source — constructor – get String – put back String, given String NEW ! • Collection— constructor – add –. . . some way of iterating … • Number— constructor • Stock. Name— constructor – is Match? given another Stock. Name

NEXT STEP: And so on … (I'm tired now— aren't you? )
- Slides: 89