[Persistence-sig] A simple Observation API
Guido van Rossum
guido@python.org
Mon, 29 Jul 2002 17:56:53 -0400
> At 05:18 PM 7/29/02 -0400, Guido van Rossum wrote:
> >Some questions about Phillip's Observable protocol. Wby does it
> >have to be so complicated? E.g. if you have to do something
> >special for method that touches an attribute without doing a
> >setattr operation on it, why not have the magic be inside that
> >method rather than declare a wrapper? (The wrapper looks like it
> >is much more expensive than another way of flagging a change would
> >be.)
>
> It's only for event compression, otherwise putting a simple flag
> operation in the method would indeed be more lightweight. Of
> course, I'm pretty sure I could write a bytecode-hacking version
> that would recode the underlying method to include the necessary
> wrapping code around its body, making it just as fast as putting the
> code inline. But I didn't want to put that much effort into an
> example. :)
I hope you were really only joking. Hacking bytecode is inexcusable
mixing of abstraction levels.
> >What exactly is the point of collapsing multiple setattr() ops
> >together? Just performance? Or is there a semantic reason? If
> >just performance, where is the time going that you're trying to
> >save?
>
> Semantics plus performance. The semantic part is that some
> "database" systems (e.g. LDAP) inherently don't support
> transactions, AND must receive a semantically valid set of
> attributes in a single update operation. I may be overgeneralizing
> this aspect, however.
I'm guessing that you'll have to do this differently anyway,
e.g. cache all changes and them force them out all at one with a
commit() operation.
> The performance save is for situations like Tim Peters' distributed
> cache example. If a change notification is going to cause network
> traffic, it would be a good idea to minimize the number of such
> notifications. It's a common situation (IMHO) to change multiple
> attributes in a set of related methods, so this supports that
> scenario while ensuring a minimal set of update events are issued.
Isn't there a way to do this in a less obtrusive way, e.g. by
buffering? I don't know much of this application area, but the
mechanism you are proposing looks very heavy-handed. I would expect
that in a realistic system, most methods would grow wrappers. And
this *still* doesn't prevent bugs like updating a list attribute by
calling its append() method without somehow flagging this operation.
(Flagging changes at the method call level seems too course-grained.
What about a method that only occasionally makes a change to a given
attribute?)
> >What's the use case for declaring a method as "touches an attribute
> >but that change should be ignored"? (If it's only __init__, a
> >lighter-weight mechanism might be sufficient.)
>
> I discovered the __init__ issue when I went to write the example
> code, and adding an ignore list seemed like the simplest way to
> solve it quickly without adding a metaclass or something else
> special to handle __init__. Also, I know I've frequently written
> classes which do the bulk of their attribute setup in methods other
> than __init__, and imagine others do as well. These days I use PEAK
> attribute binding descriptors that automatically initialize
> attributes on first-use, instead, but I wrote the Observable example
> assuming "plain-jane", "mainstream" Python with no special
> metaclasses or the like.
That's good, because I have no idea what PEAK is. :-)
Anyway, if the special handling is mostly for __init__ (or things it
calls), then a metaclass could make the notation a bit prettier.
> In general, as to the features of the API, I wrote this mostly based
> on the use cases that other folks had, although I'm certainly not
> against having event compression. :) My own requirements in the API
> are only the changeable "get" hook, and that notification of writes
> takes place after the modifications.
>
> The idea of using method wrappers to incorporate the metadata about
> what attributes are modified, was an attempt to help mask
> implementation details from the "naive" user. It seemed to me a
> less invasive form of "dead chicken waving", and also allowed for
> alternative implementation strategies for the observable's internal
> mechanism.
Maybe it's just too early to start proposing code? Or has the
discussion already moved to IRC? I'm curious about why the message
flow just stopped.
--Guido van Rossum (home page: http://www.python.org/~guido/)