[Tutor] Better structure?

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Tue Feb 1 02:27:15 CET 2005



On Mon, 31 Jan 2005, Jacob S. wrote:

> I think this thing is screaming for better structure, but previous attempts
> at using oop for it have failed.


Hi Jacob,


Ok, I see one big refactoring that should help things quite a bit.
There's a large case-analysis off if/elif/elif statements that involves
'y'.  Let me just grep for the lines here:

>     if y == 'clear':
>     elif y == 'quit':
>     elif y == 'remove lines':
>     elif y == 'return lines':
>     elif y.startswith('gatl'):
>     elif y.startswith('ganl'):
>     elif y.startswith('gotl'):
>     elif y.startswith('gonl'):
>     elif y.startswith('getpt'):
>     elif y == 'regraph':


The structure can be improves by using that dispatch-table method we
talked about a few days ago.


We can't directly apply the dispatch technique, because there's a little
bit of nonuniformity.  Some of the statements compare y by equality, while
others use 'startswith' checks.  But I think we can handle it by making
everything a little bit more uniform: we can make everything an 'equality'
check against the first word on the line.  Here's some pseudocode for the
proposed fix:


### Pseudocode
commandDispatchTable = {'clear'  :  clearCommand
                        'quit'   :  quitCommand
                        'remove' :  removeCommand
                        'return' :  returnCommand
                        'gatl'   :  gatlCommand
                        'ganl'   :  ganlCommand
                        'gotl'   :  gotlCommand
                        'gonl'   :  gonlCommand
                        'getpt'  :  getplCommand
                        'regraph':  regraphCommand

def evaluate(line):
    """Evaluates the line."""
    pieces = line.split()
    cmd, rest = pieces[0], pieces[1:]
    if cmd in commandDispatchTable:
        dispatchTable[cmd](rest)
    elif isAssignment(line):
        ...
    else:
        ...
###

The evaluate() function tries to handle the common-case stuff with a
dispatch-table method, and otherwise follows up with special-case stuff to
handle the rest of the case analysis.


One other neat feature of this is that, because we split() against the
whole line, we've broken down the line into 'cmd' and the 'rest' of the
arguments to that command.  This might also help clean up some of the
logic that grabbing the argument on the rest of the line,

    step2 = float(y.lstrip("gatl "))
    x = float(y.lstrip('gotl '))
    x = float(y.lstrip('gonl '))
    y = y.lstrip("getpt ")

You can avoid doing so many lstrip()s by using the 'rest' argument list.



Best of wishes to you!



More information about the Tutor mailing list