[Zope] Acquisition and/or Traversal ?

Dylan Reinhardt zope@dylanreinhardt.com
Tue, 28 Jan 2003 14:34:43 -0800


At 01:14 PM 1/28/2003, D2 wrote:
>Needing a starting point to understand how traversal and acquisition work

As a starting point, about 90% of what you need to know about acquisition 
can be summarized thus:
1. Acquisition works by containment or context.
2. Containment trumps (precedes) context.

To put this less formally, the relationship defined between two objects in 
the ZMI is more tightly bound than the relationship suggested by the 
construction of a URL.  This should make a lot of sense, hopefully.

Traversal is mostly a fancy way of building an acquisition context or 
specifying a particular object to render.  Since containment trumps 
context, it follows that traversal should be thought of as a less optimal 
way to use acquisition.

I would suggest that containment-oriented design (not traversal) should be 
your default choice for an acquisition strategy.  There are cases that call 
for acquisition by context and heavy traversal, but containment is easier 
to design for and more generally useful.  In most projects I've done, the 
need to perform significant traversal indicates that some refactoring may 
be in order.

>In this example company, a subsidiary must establish proposal based on a 
>product list. If it doesn't have products, it must use the headquarter's ones.
>
>1 with this hierarchy, how can i reach the Product list in the Products 
>Folder from Proposal 1  of Subsidiary 1 ?


Since it sounds like the purpose of your hierarchy is to drill down from 
general to specific, not to partition different levels of security, what 
about the following:

/
+---Products/
       - item1
       - item2
       - item3
      +---Sub1/
          - item1
          - item3
+---Proposals/
+---Etc/

The URL:   /Products/Sub1/item1
will find the item1 object in the Sub1 folder.

The URL:   /Products/Sub1/item2
will find the item2 object in the folder just above Sub1.

The name item2 can't be resolved by Sub1, but *can* be resolved by Sub1's 
container.  Ta da!  It works and you're done.  Not bad, eh?

This pattern is easy enough to nest if you should need more than two 
layers, BTW.


>2 If Products weren't folder but objects and items weren't contained 
>objects but properties of Products, would the solution be the same ?

Probably not, the way you have it, unless you specifically designed the 
objects to work that way.

If an object can't resolve a name, it will look in its container object, in 
its container's container, etc., and then back up the chain defined by 
context.  It won't be looking for an object named Products (necessarily) 
that can resolve the method item1, but for *any* object in the acquisition 
chain that can resolve "item1".  You would probably need to give each 
different Products object a different name so that you could define a 
"fall-through" acquisition relationship, thus:

/hq_products/sub1_products/item_property

In this example, hq_products is the same type of object as sub1_products... 
they just have different methods/attributes available.

When item_property *isn't* resolved by sub1_products, you've ensured that 
there is an object further up in the acquisition chain which *can* resolve 
the name (assuming the name can be resolved at all).  I'm assuming that 
hq_products is contained by something found in the containment hierarchy of 
sub1_products.  I'm pretty sure you'll have a difficult time pulling this 
off if you don't give the different Product objects different names... and 
that's a requirement that may impose significant limitations.

If you're locked into the hierarchy you've defined, you'll probably need to 
create some kind of "observer" or "viewer" method that traverses your 
hierarchy in specifically designated ways under specific conditions.  This 
is easy enough to do, but I would suggest that designing your hierarchy to 
suit your acquisition requirements might be the simpler, faster, and more 
durable solution.

$.02... HTH

Dylan