[Zope3-dev] Re: Context proposal II

Martijn Faassen faassen at vet.uu.nl
Wed Aug 13 14:31:09 EDT 2003


Jim Fulton wrote:
> I've given two:
> 
> - Looking up components for objects that don't track containment
>   information.
> 
>   It is not acceptable to me to make containment management a prerequisite
>   for component usage. It is also not acceptable to me to fall back to
>   global component registries when no context is available, as is done now.

I can't argue with this use case, though I cannot really guess how
important this will be in practice.

> - When using components from a different site, I want the use to reflect
>   local customizations as long as those customizations don't break
>   the invariants of the used objects.

This is what we're arguing about. I'm worried that context expectations like
this are a) hard to know about b) hard to meet c) can lead to hard to
debug code.

> If a used object has depenncies on
> specific instances or on it's specific site, it should provide an adequate
> context so that invariants are met.

> ...
> 
> >  * Jim feels that there is no problem with the request's context 
> >  determining
> >    the lookup context of all the components which are used.
> 
> No. I've acknowledged that sometimes components have dependencies on
> their containing site. In these cases, the components should supply
> a containment context when they look up components that have to come from
> their site,

Would it be bad if this behavior were actually the default, and using
the request context is the behavior that is invoked explicitly? 
Using the request context properly seems to me to be harder to get
right (also in client code).

[snip data dependency and 'hard reference' discussion]

> >  * If you use a component in another site, this means that your own
> >    site's context should provide all the components this component
> >    tries to look up (and recursively onward).
> 
> Right
> 
> >     Jim states that
> >    having to satisfy these criteria won't be a problem in practice.
> 
> Because in most instances of this, the using site simply customizes
> the source site.  Usage if components accross unrelates sites will be
> extremely rare IMO.

I'm worried even in the case of related sites, though. 

If I have a subsite which has certain behavior modified by a local
adapter, and I call methods on objects in this subsite, this adapter
will not be used unless the adapter lookup explicitly uses container
context. Since I can't control all adapter lookups (I may be using
components I don't maintain myself), I can't pass the context explicitly.

I would expect such subsites with a few different adapters or utilities to be
reasonably common. I can imagine a content management site that allows
end users to add specific adapters or utilities to subsites
(through a completely specialized UI), to configure certain application 
behavior. I also don't consider it very rare that code is triggered from 
higher up in the tree that calls methods lower in a tree.
Imagine for instance a publication screen that allows one to publish multiple 
objects. Imagine being able to place a utility that takes some special action 
in case of a publication, such as sending email.

If adapters and utilities are looked up by request context, the subsite 
configuration may have no effect at all in such a case.

You can argue that I should lookup those adapters or utilities in 
the container context, but this will not be possible if I'm using
existing adapters and utilities and *they* lookup other
adapters and utilities. 

I guess one could also argue that I shouldn't do this, but then I'd
like to know why not, and what should I be doing instead?

Interestingly views seem to want different behavior. I expect it to
be a common scenario to have subsites which override various views.
Often large sites have a common set of public navigation and layout, 
but some subsites need to override parts of this, and other subsites will 
want to completely override layout completely.

Views are looked up programmatically less often, and if so one can make
a good case that the request context is the right place to look up 
views. If I override the way a form widget looks in a subsite
I probably don't want this to affect views on the higher-up site.

On a different tack, I expect the following invariant to be in place
when programming:

Given a system in state X, and a method m on an object with a set of
arguments A, the result R of method call will be the same no matter 
which client code does the method call. If I want it to depend on
the client code's context, I want this to be explicit.  The traditional
way is to state this explicitly in the method argument lists (context).
I can imagine Zope 3 needs a slightly more implicit way to do it,
but then I expect this to be documented well for each such method,
and methods with this kind of behavior to be rare.

> ..
> 
> > *  If there are problems then the code you're using is actually 
> >    misbehaved with respect to component lookup and use and you shouldn't 
> >    be
> >    using it that way at all. Jim says they're "wild animals" and I
> >    should forget about using them.
> >
> >    My worry here is that we're actually making simple use much
> >    harder than it should be.
> 
> I don't think that sharing objects accross unrelates sites is simple
> usage.

It happens with related sites. That's simple usage all right.

The unrelated site argument can also be made in the context of scriptability.

If I want to write a script that just sits in my Zope somewhere and can
take any object as an argument, and reports on it by calling a method on i
it (say we get the title), I don't want to have supply all possible
components that object can look up in my context. I have no clue
what these might be in the first place.

> >     Jim argues that code is flawed if it depends on
> >    a particular instance implementing an interface and cannot use
> >    another instance implementing its own interface. I disagree
> >    (first point).
> 
> I don't know what you just said.  I have no idea what you are asserting
> that I'm arguing.

I think I miswrote.

I interpreted you as saying that if code looks up a component by interface, 
then this code is flawed if it cannot handle another component found
than the one supplied by its containment context. You also argued
that typically as interfaces are used this won't occur. I disagreed
with this (data dependency and such).

[snip]
> You will be able to make connections as tight as you want them to me.
> Containergeddon will make this much easier and cleaner.

But I don't have control over all code. If code makes a connection not
tight enough, I'm screwed if I want to use it. :)

[snip]
> If code has such tight dependiencies, it should reflect the dependcies in 
> it's implementation. If you aren't sure, always supply the context.

The default behavior of lookups (no explicit context specified) 
express weak dependency. Basically such a lookup promises that this
code will work correctly whatever object is found; one has to
be very careful about keeping state based on what was found as a different
object may be found at any call into it.

Code with such loose dependencies is hard to write. Why then is this the 
default and normal way to do lookups? Naive programmers will trip up,
finding their code works in some contexts but then suddenly fails in
others.

> >    Sometimes being able to use horribly flawed code is better than not 
> >    being able to use any code at all. In Jim's proposal it seems to me 
> >    that the only thing left to do when you want to use a 'wild animal' is 
> >    to forgo Python method calls and instead use the publisher machinery, 
> >    starting up a new thread as the context is thread-global..
> 
> I sugges that you simply not do this. 

I wasn't suggesting I do this, it is rather horrible. But it is a consequence
if I *really* want to use this code.

> There are going to be objects that
> expect tehir usage environment to provide what they need. If you use them
> and don't provide what they need, you lose. I really don't see a problem
> with that.

I don't see a problem with the existence of such objects. I just want them
to be rare.

> >    I'm worried also that this will affect scripters. Calling
> >    methods on objects in some other container is not that rare.
> 
> No, calling methods on objects in other *sites* is.

See example above. Calling methods on subsites is not rare and not
rare for scripters.

> >    This other container may be a site by virtue of having its own
> >    components installed (adapters, etc). Those adapters won't be
> >    used though if called from within another container. Does this
> >    mean that the scripter somehow has to deal with the reason why?
> 
> Maybe the scriptor shouldn't do that.

The scripter cannot call 'publish' on a list of objects found, say?
A scripter just wants to call methods and expects them to work on one
instance if they work on another instance in a similar state. 
The scripter depends on the invariant expressed before.

> The scriptor has to rely on some sort
> of common facilities.  They shouldn't use facilities that aren't available
> for the object's they are using.

But they are, they're just not in the script's context, they're in that
object's container context. The scripter can't go in and rewrite all those
objects so that they pass the container context as their context to
lookups.

Regards,

Martijn




More information about the Zope3-dev mailing list