[Zope3-Users] newbie design questions for UI to external data

Shaun Cutts shaun at cuttshome.net
Tue Feb 14 15:07:57 EST 2006


Gary,

Thanks for the reply.

> On Feb 13, 2006, at 10:33 PM, Shaun Cutts wrote:
> 
> > Um...
> >
> > I guess I must have asked too many questions at once :)
> 
> :-) and this is still a bit much for me.
> 
> > I've implemented
> > a first pass of a container for external data and got it working on
> > some
> > of my collections.
> >
> > I've included the (first pass of the) base DBContainer and
DBContained
> > objects for criticism, and would be very grateful if anyone would
like
> > to take a crack at it.
> 
> It looks like an interesting approach--more low-level than I would
> have expected for a first cut, and *maybe* more low-level than
> necessary.  I wish I had more time to look at it.

If there were anything more higher-level, I would be happy.... I will
eventually be needing "paged" collections to, though, so I can't give up
too much control.

> 
> > Keep in mind, this is my first time working with the system, so I'm
> > sure
> > I'm going about some things the wrong way. In particular, I already
> > think:
> >
> > 1) Instead of have the contained object update the container, I
should
> > rely on the event notification system.
> 
> Events are a tool for disconnected notification.  calling a method on
> an object is sending a message directly to the interested party.  Not
> everything should be an event.  If a communication between two
> components is a core aspect of your design, maybe direct method calls
> are more appropriate.

The problem now is that the default edit view uses __setitem__ for the
contained object, so I get one db update per column, whereas (I hope!)
the event is fired after all the column updates are complete. Not a
problem for the prototype, but maybe annoying in production system when
Postgres is busier with other users as well. Of course, I may be
overriding the default edit view anyway....

So the problem isn't the coupling between DBContained and DBContainer
per se. Its sort of like I want the editView to enforce a transaction
protocol, and want to use the Event as a proxy for "commit".

Note: I don't think I want dirty object in the system; otherwise I could
use a lazy protocol where the container just checks -- say at
demarshalling time (but probably on shutdown at least, if we are
interrupted?) -- whether it has any updates to write. If I did want to
go to a lazy protocol, is there a way to register things for getting
triggered on shutdown.

> 
> > 2) Right now, the system works by translating objects "at the
border"
> > (in IExternalContainer). Some translation is necessary, for
> > instance, to
> > move from mx.DateTime to datetime.datetime, but still I think I
should
> > somehow be making use of the "adaptor" interface.
> 
> If there's not an object to adapt then you have to start somewhere.
> My glance at the code seemed to show that you were making a
> reasonable choice.  Another approach might be to have an abstract
> "row" object that could represent any columns (a dict or something),
> and named adapters registered for the row interface plus the name of
> the generating table.  I dunno, do what your app needs and refine it
> as you discover what works.
> 
I actually do have a row object from my database code... but (as I
learned) it is a bit of a pain to use directly, since: 1) datatypes are
somewhat non-standard (dates, particularly), and 2) it is a bit messy to
use with annotations because Row uses __getattribute__, though this is
probably a design flaw in the Row class hierarchy.

My thought was that I might want to be adapting my row objects (or their
interfaces to be precise). Indeed, I am, but in a nonstandard way, as
"IExternalDatabase"-derivatives do the translation. My plan now is: have
the DBContained base class be a "protoadapter" that does all the column
datatype translations and validation; its subclasses will adapt specific
Row-derived classes, which have concrete sets of columns.

I guess there is no particular machinery to use to present this pattern:
one hierarchy adapts another hierarchy?

> > 3) Along these same lines, IDBContainer._containedType should
> > really be
> > an interface (Object( schema = IDBContained ))
> >
> > Note: is there a tutorial on writing containers anywhere I should
have
> > read? I mainly figured this out by banging on it and fishing around
in
> > the code. I'd love to figure out, for instance, what is really
> > happening
> > with the traversals (with some interaction diagrams). I do think it
> > was
> > harder than it should have been. (But, then again, I think that
about
> > most things...:))
> 
> Don't know of a tutorial.  Sounds like you are interested in
> traversal, though, which is different.   Look at zope.app.traversing,
> or zope.app.container.traversal.  The headline is that there are two
> kinds of traversal: URL path traversal and TALES path traversal.
> They have different adapters.

When debugging, I had a lot of problems understanding what was happening
because I didn't understand how traversal was trying to get data... It
would just be nice to have more design doc -- especially interaction
diagrams -- to refer to for some of the more complex parts of the
system. (Stephan's book's diagrams for events are useful.)

> 
> > BTW in my humble opinion, ILocation.__name__ is not well named. When
I
> > first got an error referring to __name__ I thought it was expecting
a
> > class object. And what happens when, for some strange reason,
someone
> > wants to put a class in a container, and doesn't like its default
> > name?
> 
> Not sure if that's a real use case for an ILocation.
> 
> That said, it's a reasonable POV to say that Zope shouldn't claim
> __*__ names.  But we do, so, well, yeah, we do. ;-)
> 
> Gary

I would prefer that zope names have some unique prefix... maybe :
__zope_name__. This would also help greping/googling. ("__name__" is a
particularly conflict prone case.)

Thanks,

- Shaun





More information about the Zope3-users mailing list