890 likes | 1.06k Views
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?.
E N D
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.
PayrollMaster Employee PersonnelFile TimeCard TimeCardFile Check SS# Hours Payroll Classes
Time getHours Program PersonnelFile main lookup PayYourself Employee TimeCard File getCard Payroll Master TimeCard DoPayroll getTime SS Check getSS match print Payroll Objects
Program PersonnelFile PersonnelFile PersonnelFile main lookup lookup lookup TimeCard File TimeCard File TimeCard File getCard getCard getCard Payroll Master Payroll Master Payroll Master DoPayroll DoPayroll DoPayroll Payroll Program (1)
PersonnelFile lookup TimeCard TimeCard TimeCard TimeCard File getTime getTime getTime getSS getSS getSS getCard Payroll Master DoPayroll PayrollMaster: DoPayroll (1)
PersonnelFile lookup get SS get SS get SS get SS TimeCard TimeCard File getTime getSS getCard Payroll Master DoPayroll SS SS SS SS match match match match PayrollMaster: DoPayroll (2)
Time Time Time Time Time getHours getHours getHours getHours getHours PersonnelFile lookup get Time get Time get Time get Time TimeCard TimeCard File getTime getSS getCard Payroll Master DoPayroll SS match PayrollMaster: DoPayroll (3)
Time getHours PersonnelFile lookup PayYourself PayYourself PayYourself Employee Employee Employee TimeCard File getCard Payroll Master TimeCard DoPayroll getTime SS getSS match Personnel: Lookup
Time getHours PersonnelFile lookup PayYourself Employee TimeCard File getCard Payroll Master TimeCard DoPayroll getTime SS Check Check Check Check Check Check getSS match print print print print print print PayrollMaster: DoPayroll (4)
Time getHours Program PersonnelFile main lookup PayYourself Employee TimeCard File getCard Payroll Master TimeCard DoPayroll getTime SS Check getSS match print Payroll Program (2)
SMART and HELPFUL Objects 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!)
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
Statement of Problem Possible Objects Primary Object Behavior Interface Sample Use Implement Kindergarten OOD
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 stocks based 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 message to 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 t create Portfolio p to p: get Value v, given t to 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 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: 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 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: 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 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 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 src while h was created successfully { to c: add h create Holding h, given src }} … STATE: Collection c }
Portfolio Class: class Portfolio { constructor(TokenSource src) { create Collection c create Holding h, given src while h was created successfully { to c: add h create Holding h, given src }} Value getValue(TickerTape 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 }
Completed: Portfolio Yet To Complete: TickerTape TokenSource Collection Holding Value Class Summary
Details of Remaining Classes: • TickerTape— constructor • TokenSource — constructor get String • Collection— constructor add ... some way of iterating … • Holding— constructor, given TokenSource get Value given TickerTape • Value— constructor, given an integer value increase, given a Value print
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: getValue class Holding {Value getValue(TickerTape t) {to t: get Value v of stock named by my StockName to v: multiply by my Number return 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 sn to v: multiply by n return v}STATE: StockName sn Number n }
Implementing Holding: constructor class Holding {constructor(TokenSource src) { create StockName sn, given src create Number n, given src} ... STATE: StockName 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(TokenSource src) { create StockName sn, given src create Number n, given src} Value getValue(TickerTape t) { to t: get Value v given sn to v: multiply by n return v} STATE: StockName sn Number n }
Completed: Portfolio Holding Yet To Complete: TickerTape TokenSource Collection Value Number StockName Class Summary