[Zope-dev] Design explanation (Was: SkinScripts instantiating new objects)

Stefan Karlsson stefan@everynet.se
Mon, 19 Feb 2001 17:43:28 +0100


At 16:21 2001-02-16, Steve Alexander wrote:
>Stefan Karlsson wrote:
>
>> 
>> BTW is it possible to save the ProjektHandler instance persistently
>> in the attribute? Is there an easier way than creating a separate
>> specialist for the ProjektHandler class and storing the instances there?
>
>I think you're getting design and implementation confused here.
>
>Should ProjektHandlers be a Dataskins? If so, they should live in their own Rack.
>Or, does a ProjectHandler really belong as a part of the instance of something else?
>In this latter case, you could add a ProjectHandler as an attribute.
>As to whether this is a wise thing to do; well, I can't say, as I don't know what problem you're trying to solve.

I have found a workaround for the 'Error computing attribute' problem by 
instantiating the ProjektHandler object directly in __bobo_traverse__:

def __bobo_traverse__(self, REQUEST, name):
    if name=='projekt': return self.getNewProjektHandler(self,id, 'Projektagare').__of__(self)
    else: return getattr(self, name)

For those of you that are interested in a long explanation of how I 
designed the system, read on...

A ProjektHandler is a ZPHandler that is a "virtual folder" that 
looks like a normal Zope folder but doesn't store any objects in itself. 
Instead the storage is delegated to ZPatterns. There is also an OMHandler
class that implements the same interface as ZPHandler but stores the 
objects in itself like ObjectManager, but that's another story.

In each class that has an aggregate to another class I instantiate
a handler for that other class. As an example, look at the 
UML class diagram below. We can see that both A and C has an 
aggregate to class B, that is, a one-to-many relationship. 
A also has an aggregate to D.

X=diamond=aggregate

+-----+   * +-----+
!  A  !X----!  D  !
+-----+     +-----+
   X
   !
   ! *
+-----+
!  B  !
+-----+
   ! *
   !
   X
+-----+
!  C  !
+-----+

So what we need is a handler class that manages objects of class B,
so we create a BHandler by simply subclassing ZPHandler and telling
it what objects to handle. One BHandler instance is put into A and 
another is put into C. Both instances are called 'bs'. We also need a 
DHandler that is put into A.

The nice thing is that it is very easy to get management tabs
for B:s and D:s in A and B:s in C in the management interface.
Another nice thing is that B instances actually seems to exist 
in multiple parents! And all objects seems to exist as normal 
Zope objects even if the are stored in SQL database. 

Now instantiate objects of type A, B and C and call them a1, b1, c1.
 From python we can write a1.bs.getItem('b1) to get the b1 object.
We can of course also write c1.bs.getItem('b1') and get the same object.

The handler attribute bs is instantiated by a ZPatterns 
skinscript as a new object when they are first accessed in
every transaction

Now wouldn't it be nice to access this URL:
http:/server/path/to/a1/bs/manage_workspace
to get the management interface for the B objects belonging to A?

But here comes the problem! This doesn't work for me. I get the
'Error computing attribute' in ZPatterns. I have also
tried calling self.a.bs.getItem('b1') in __bobo_traverse__ but
get the same error. 

As I said I have found a workaround but I suspect it's a bug in ZPatterns...

Anyway, this was the way I designed this system and it would be nice
to have some comments.

Thanks Steve for your help!

/Stefan Karlsson
 Everynet Consulting