[Tutor] Code critique please (OOP strategy)

Lloyd Kvam pythontutor@venix.com
Tue, 01 Jan 2002 10:13:12 -0500


Yet another python module I hadn't noticed, cmd.

Suggestions:
self.purchasePrice = int(purchasePrice*100)      # Amount in cents
(and elsewhere)

Presumably you are trying to avoid rounding problems from floats.  I did not
trace everything through, but I think you will need to explicitly convert to
integers to be safe.


You want to avoid mixing user interface concerns into your data processing
classes (Portfolio, Stock).  You already did that by putting the UI into main.
I believe modifying this suggestion to create a PortfolioCMD class that
chooses or creates a portfolio for StockCmd.  In general, your UI "knows"
about the classes that do the work, but does not inherit from them.  This
way alternative interfaces (HTML, SOAP, etc.) can be provided without
changing the underlying classes.

Michael P. Reilly wrote:

> On Mon, Dec 31, 2001 at 08:46:48AM -0600, Timothy Wilson wrote:
> [rest snipped]
> 
>>>you could make a menu class or function, but all that would do is move the
>>>code out of main.
>>>
>>Here's an example:
>>
>>The main() function contains the following code to delete a stock:
>>
>>elif choice.upper() == 'D':
>>    ticker = raw_input("Delete which stock (type a ticker symbol): ")
>>    for stock in p.contents:
>>        if stock.ticker == ticker.upper():
>>            p.delStock(stock)
>>            print "Removed %s" % stock.ticker
>>
>>The delStock method is:
>>
>>def delStock(self, stock):
>>    self.contents.remove(stock)
>>    self.modified = 1
>>
>>Is is correct to ask for the ticker symbol in the 'elif' or should I do
>>that in 'delStock'? My reason for doing it the way I did was to make the
>>code as reusable as possible. That may or may not be a valid reason in
>>this case. I'd appreciate feedback on this point.
>>
> 
> You might want to look at the cmd module; it's design is meant for
> user keyboard input.
> 
> import cmd
> 
> class Portfolio(cmd.Cmd):
>   prompt = '(O)pen existing portfolio or (M)ake a new one? '
> 
>   def __init__(self):
>     cmd.Cmd.__init__(self)
>     self.portfolio = None
> 
>   def do_M(self, args):
>     self.portfolio = Portfolio()
> 
>   def do_O(self, args):
>     file = raw_input("filename: ")
>     self.portfolio = Portfolio(file)
> 
> class StockCmd(cmd.Cmd):
>   prompt = '(A)dd/(D)elete stocks, (S)ave file, (U)pdate, ' \
>            '(R)eport, or (Q)uit? '
> 
>   def __init__(self, portfolio):
>     cmd.Cmd.__init__(self)
>     self.portfolio = portfolio
> 
>   def do_A(self, args):
>     ticker = raw_input("Ticket symbol: ")
>     companyname = raw_input("Company name: ")
>     ...
>     p.addStock(s)
> 
>   def do_D(self, args):
>   
>   ...
> 
> then you create new instances of these classes:
> 
> cmd = PortfolioCmd()
> cmd.onecmd()  # only one prompt and return
> if cmd.portfolio is not None:
>   StockCmd(cmd.portfolio).cmdloop()
> 
> This makes things a bit more extensible and teaches your students to
> reuse library classes.
> 
>   -Arcege
> 
> 
> _______________________________________________
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor
> 
> 


-- 
Lloyd Kvam
Venix Corp.
1 Court Street, Suite 378
Lebanon, NH 03766-1358

voice: 
603-443-6155
fax: 
801-459-9582