Best Object-Oriented Design in Python

37 views
Skip to first unread message

Aaron S. Meurer

unread,
Dec 16, 2010, 9:51:58 PM12/16/10
to sy...@googlegroups.com
In the Risch Algorithm there is a function called build_extension(), which takes in an (Expr) expression and converts it into a bunch of Polys, etc. for use in the internal Risch Algorithm functions. Now, currently, it returns a tuple of seven items. Up until now, I have been able to get away with passing through two of those items through each function in the algorithm, but around the end of the summer I discovered that I really need to be passing at least four more of these items.

So, I decided that the smartest thing to do would be to create a simple object to wrap around all of these. It would just be a simple C struct-like thing, something like

class DifferentialExtension(object):
def __init__(self, f, x):
vars = build_extension(f, x)
self.attr0 = vars[0]
self.attr1 = vars[1]
etc.

So I did this, but then I got to thinking if it would be smarter to do this slightly differently. For example, would it be better to make build_extension() return a DifferentialExtension object (and do away with __init__). Or, since this is the only place in the code where build_extension() is ever called (or will ever be called), should I make it a method of DifferentialExtension? Is this method of storing information even the best way to do things?

Maybe this all seems superficial, but this is my fourth attempt at an API to pass this information around, and I would really like to get it right this time. So which one of these is the most Pythonic? Object-Oriented programming is one of my weak points, so I really don't know how to come up with the best design. One thing I do know is that it is very easy to design a poor system using it, so I am ever cautious.

Aaron Meurer

Ronan Lamy

unread,
Dec 17, 2010, 2:01:37 PM12/17/10
to sy...@googlegroups.com

The purpose of build_extension() is obviously to build extensions or, in
other words, to create instances of DifferentialExtension. This means
that it's a constructor - and in this case the only constructor - of
DifferentialExtension, so it should *be* DifferentialExtension.__init__
instead of merely be called by it.

>
> Maybe this all seems superficial, but this is my fourth attempt at an
> API to pass this information around, and I would really like to get it
> right this time. So which one of these is the most Pythonic?
> Object-Oriented programming is one of my weak points, so I really
> don't know how to come up with the best design. One thing I do know
> is that it is very easy to design a poor system using it, so I am ever
> cautious.

The whole point of object-oriented programming is that you should see
class instances not just as bundles of code and data but as actual
concrete objects in your problem space. Attributes should model
characteristics of the object and methods should model actions that can
be performed by or with the object. If you analyse your code in terms of
the underlying objects, most design decisions become easy. Tricky
problems only appear when there's ambiguity or uncertainty in the
definition of the objects.

HTH
Ronan


Aaron S. Meurer

unread,
Dec 17, 2010, 3:22:24 PM12/17/10
to sy...@googlegroups.com
Thanks. Actually, now that I think about it, I can simplify the code of build_extension() a little bit by doing this. Right now, I have two functions inside of build_extension(), and am using some global variables to pass stuff between them, but I think it would be better to make those functions class methods and just use the class attributes instead of global variables.

I guess part of the reason that this wasn't as apparent to me, aside from the fact that I had a hard time looking at the code in the new way instead of in the way that it is now, is that build_extension() is very large—over 200 lines including those internal functions—and it seems like an awful lot to put in an __init__() method.

Aaron Meurer

Reply all
Reply to author
Forward
0 new messages