Puzzling OO design problem
Jack Diederich
jack at performancedrivers.com
Fri Apr 8 22:54:20 EDT 2005
On Fri, Apr 08, 2005 at 06:40:54PM -0700, George Sakkis wrote:
> > Err, you might want to explain what these things do instead of an
> > abstract description of how you are doing it. It looks like you are
> > using inheritance in the normal way _and_ you are using it to handle
> > versioning of some kind (maybe stable interface releases? I don't
> know).
> >
> > Let us know what parts need inheritance for, and what you have
> > just been using a side effect of inheritance for as a convenience
> > (versioning, I think).
> >
> > A more concrete example would be easier to comment on, if possible
> > do a simple one (maybe just two classes with two versions each).
> >
> > -jackdied
>
> I intentionally abstracted the problem to remove the irrelevant
> details, but here's a more concrete (though still simplified) example.
> I hope it is more clear now.
<boiled down version of George's exmaple>
> def worldModelFactory(version):
> if version < 2: return WorldModel()
> else: return WorldModel_v2()
>
> class WorldModel_v1(object):
> class Player(object):
> def foo(self): pass # v1 implementation of foo()
>
> class WorldModel_v2(object):
> class Player(WorldModel_v2.Player):
> def foo(self): pass # v2 implementation of foo()
So you are using the WorldModel_* classes as a namespace to hold a
set of classes that might inherit and extend or redefine the previous
classes in a WorldModel_* namespace. This seems to do what you wanted
in your original post, namely if a class is defined in v1 but not in v2
that v2 would just use v1's implementation. WorldModel_v2 will inherit
Player from _v1 by default, so that should work OK out of the box.
So you should be fine there, but I think your question is more practical
than "what is the proper OO way to do it?" which is a bit of a shibboleth
in python. We like "what is easiest and readable?" So here are some
practical recommendations (well, at least that's my intention).
Are you using the *_v1 naming convention for backwards compatibility?
Backwards compatibility is a giant pain in the ass, I notice you are
posting from a .edu address so if this is just something you are working
on by yourself or in a small group drop the versioning aspects from the
code. Talking to the other people in the group is easier.
>From your example (which I over-pruned) it looks like you are using
the WorldModel namespace to define parameters for running an iteration
of a game. The classes under "WorldModel" are something like
the rules/physics definition (MovableObject), coordinates of the team-A
goalpost, coordinates of the team-B goalpost, team-A strategy (Player),
and team-B strategy (also Player). WorldModel would be the gameboard.
If so, make WorldModel just a board - drop putting Player etc under it
as a namespace, and give it a run() function that takes parameters.
Name the Player derivatives as PlayerDumb, PlayerSmart, PlayerAggressive
etc, you'll probably have a lot more of those than goals or physics rules.
The actual main routine would look something like
ob = WorldModel() # standard 100x100 board
winner = ob.run(physics=MovableObject, # defines friction and gravity
team_a_goal=(50,25),
team_b_goal=(5,5),
team_a_strategy=PlayerDumb,
team_b_strategy=PlayerAggressive,
)
print "Winner is ", winner
I wrote more than I meant to, but the basic idea is don't use classes
when you don't need to - it just makes things more complex. That
should give you more time to tackle the interesting parts (player
strategies, I'd imagine).
-jackdied
More information about the Python-list
mailing list