Python evangelists unite!

Jason Voegele jason at jvoegele.com
Tue Dec 4 10:53:10 EST 2001


> > The problem with this is that it defeats the idea of transparent
> > persistence.  One goal of object databases is that persistence is not
> > limited to a subset of the class heirarchy.
> 
> Okay, I can see that. In other words, the hierarchy should express the
> relationships between objects, not a particular feature of certain objects?

I'm not sure I understand what you're saying.  My original point was
that persistence should not be limited to objects whose class
subclasses "Persistent".  *Any* object should be capable of
persistence, whether it's class is Integer, or MyClass.

> > ...
> > Some OO databases ignore this and force applications to use
> > "Persistent" superclasses or interfaces.  IMO, this is a very bad
> > idea.  Consider that you may have a million instances of a class, only
> > one of which is persistent (by the reachability definition).  If the
> > class has to subclass a "Persistent" class, all of those million
> > objects have to carry around the Persistence baggage, even though only
> > one of those objects needs them.
> 
> I thought only the persistent objects would subclass the Persistent class;
> how does the persistence baggage get into objects of classes derived from
> Transient? Wouldn't only leaves, so to speak, of the hierarchy derive from
> Persistent or Transient anyway?

That's precisely how it works, because individual objects can have
methods added to them.  If they didn't have this capability, then all
objects of a particular class would have to support persistence.

I think an example is in order.  Say I have a class called "Book",
that represents a book having a title, an author, a date of
publication, etc.  In my application, I might instantiate a million
Book objects.  But say that I only need to store one of them in the
database.  Given the ability to add members to a specific object, I
can add persistence support methods (such as object_id, mark_modified,
etc.) to the single book instance that I need to store in the
database.  (More precisely, the database binding could add these
methods for me!)  If Ruby did not have this ability, the Book class
would have to inherit from some sort of Persistent class.  This would
mean that all one million books have these methods and variables to
support persistence, even though only one book object actually needs
them.

> 
> > Adding the persistence baggage to individual objects as necessary
> > provides a much simpler and scalable solution.  Simpler because
> > application developers don't have to bother with subclassing (or
> > implementing) a Persistent class (or interface).  More scalable
> > because the persistence support is added to *only* those objects (not
> > classes) that need it.
> 
> I'm not sure how the singleton stuff is more scalable (though I'm sure you
> have more experience than me).

To be fair, I don't know that it's any more scalable, but my intuition
tells me that it should be.

> Hypothetically (yeah, I'm on shaky ground
> here), what if you had more than one major behavior (besides just
> persistence) that might vary between objects of a given class? Mightn't it
> get messy to keep track of which objects are which? (I suppose, though, you
> don't have to "keep track" of which ones are persistent; they just act
> differently.)

Yes, you just answered your own question :-)

In addition, dynamic languages aren't concerned with such strict
semantics.  Type is often defined by the messages an object
understands (whether those messages where implemented by the object's
class, or whether they were added to this specific instance does not
matter for a dynamic language).

> I wonder if it wouldn't really be clearer just to declare
> trivial classes which inherit multiply from Persistent/Transient, other
> behavior implementations, and other parent classes.

You could do this, but then you force application developers to do
things you could automate for them.  And it doesn't provide any
benefit anyway.  Adding this kind of behavior at the class level means
that all instances of that class provide that behavior.  Most of the
time, this is what you want, but sometimes it is just incorrect.  See
the Book example above.

> (Of course, in Python
> there's no such thing as a trivial subclass definition; you've got to
> overload __init__ specifically and call __init__'s in each base class. This
> ticks me off to no end.)

I'm just starting to play around with Python, so I can't comment on
this.

> Also, a more technical concern: shouldn't every Ruby object need hooks in
> place so that any single method could be overridden in individual objects?
> I'm envisioning a class instance with a function pointer for each method ...
> that's a nasty thought. Or does each object carry a list of overridden
> methods, to be checked with each method call? Isn't there significant
> overhead either way? Or (most likely) is it implemented in too clever a way
> for me to come up with? :-)


The Ruby object model is very flexible.  Classes have methods, objects
have methods, objects can have a class created specifically for their
own use, objects or classes can mixin methods from a module, etc.  A
lot of the (presumed) overhead is handled by method caching.  See:

    http://www.rubycentral.com/book/classes.html

for a description of the Ruby object model (although, unfortunately,
the very helpful figures from the printed book are not available in
the online version.)

-- 
Jason



More information about the Python-list mailing list