[Zope3-dev] Context and Component Lookup

Martijn Faassen faassen at vet.uu.nl
Fri Aug 8 13:32:14 EDT 2003


Jim Fulton wrote:
> So, I think we have a number of choices:
> 
> - If the author of A knows it's needs are special, it can arrange
>   for A to supply it's own own context when looking up the adapter
>   it needs.  In this case, it takes the chance that it will not
>   use an adapter available where it's used, but it may not care.
> 
> - If the author of A knows it has this need and that the need
>   might or might not be filled where it's used, then it can
>   first try to get the adapter using the context in which it's used,
>   and uses it's own context if that doesn't work:
> 
>     a = queryAdapter(self, IBar)
>     if a is None:
>        a = getAdapter(self, IBar, context=self)
>
> - If the author of A has documented what A's requirements are,
>   then he might just decide that people who use A without providing
>   what it needs deserve to lose.  This is the implest approach in
>   many ways, although, of course, it has it's drawbacks.

This is a nice overview.

Is a possible drawback that the component found wants to look up
other components that you need to satisfy as well? I mean, could this
be different dependent on which component is found, or is this actually
not a worry as which components are found (that can find other components)
are under control of the calling context.

Anyway, I'm still slightly concerned that the implicit behavior of
depending on the request's context is the default, instead of the
attempt to depend on the local context..

> >>I suggest that it is often not the code that looks
> >>up the views that cares. The system designer cares.
> >
> >Yes, as a system designer I care that I don't have to satisfy a lot
> >of criteria in my context just in order to use an object somewhere
> >else. In my mind, that object has its own context.
> 
> So you and I discussed this in IRC.  So we have the hypothetical situation
> that object C in S1 wants to use A. It wants to use A in such a way that
> the default place that A will look for components is in S11.  I don't
> have a good answer for this.  I have to admit that I'm somewhat skeptical
> that this is a situation that will occur much, if at all, in practice.
> I'm open to suggestions.

It seems to me that whenever code manipulates objects in another container
at all there's a chance of this happening, and I, the writer of calling the 
code, have no indication that this *cannot* happen. There may be a
site management folder placed there by someone and this can now cause
my code to break. Or if there's an existing one, any chance to it
can cause my code to break as I haven't supplied the right components.

I seem to have no way to avoid this; the only case where this does not happen
if the other person has made sure to use the context=self pattern described
above in all component lookups; I'm not sure this is even possible as
some framework code may be doing this too..  At least in that case
it'll presumably work with a bunch of well known interfaces, though I'm
still concerned there may be a kind of 'spreading' effect as soon as one
object (implementing a well known interface) is put in the mix that does
component lookups of some less-common interface.

> >>>What if I have two interfaces that do some storage, one using a 
> >>>relational backend and the other the ZODB? Exact same interfaces but I 
> >>>certainly don't
> >>>want to switch from one to the other just like that.
> >>
> >>Why? What difference does it make. The client of those interfaces 
> >>shouldn't
> >>care.  If the client's do care, there's a problem with the interfaces.
> >
> >Does that mean storage needs to be explicit in the interface?
> 
> Only if the client cares about the storage.  It isn't not in the interface,
> the client probably doesn't care. If it does care, the client should
> be using a different interface.

The client doesn't care about storage, it just assumes it's using
the *same* storage as another client. If it has to supply it in the
context itself, it can never be sure.

> > If I'm telling
> >
> >somewhere.fridge.store('cheese')
> >
> >from my context, where I have a utility that implements IFridgeStorage
> >using a ZODB backend, and then I go do this from some other context where
> >the utility is supplied that uses a relational backend, I'll get
> >confused, right?
> 
> Why would you get confused?  My family used to kave an old Kerosene 
> refrigerator.
> No I have an electric one. I didn't have any problem with thw switch. The 
> interface
> was the same. They both had doors and the stuff inside stayed cold.

Well, if you had the kerosene fridge in your context, and your wife has
the electric one in her context, and you're putting stuff in and she
can't find them, this is rather odd, innit? :)

[snip]
> >Perhaps I'm just completely missing the point, but I see difficulty
> >both with this, and with the requirement that I suddenly need to 
> >supply a lot of components that my site doesn't directly deal with,
> >just in order to use a different area of the system. 
> 
> Sometimes, it just doesn't pay to try to do this.  It may be, that I'll be
> unable to use an object from another site if that object:
> 
> - Has things that it expects to have met by the using environment, and
> 
> - I can't meet those needs.
> 
> Sometimes, you just can't keep a wild animal as a pet. :)

If it were supplying its own environment I would not have to meet its
needs in order to use it. I have to supply its environment now, and 
this causes problems in that I may not know what to supply at all.
Someone else may be supplying a different environment. If i use a
registry in one location it may be tucking away its data depending on
my context, and that means someone else using the same registry with
a different context in hand may never be able to find it again.
They can't control what context I am using, and I can't control
what context they are using. If the registry has its own context,
this is not a concern.

> >If I'm going to show a view for a content object that's in a different 
> >folder which supplies its own views, I now have to supply those views 
> >myself in
> >order to make things work.
> 
> Only if you use those views. 

I can't use those views, I have to supply them myself. I *want* to use
those views.

> > This seems odd to me; I should only have to do that
> >if I'm going to use this content object in my own context, I thought.
> 
> I guess it really boils down to what you want to do.  If an object really
> needs things that are only found in it's place, then it should supply an 
> explicit
> context when it looks things up.
> 
> I think that, in practice, this won't be such a problem.  Despite my 
> original
> proposal, I don't think there will be much sharing accross unrelated sites.
> When sites are related, designers will arrange for the necessary components
> to be in place for sharing to take place.

The only way to be sure I can see is to put them all in the root of the site..
For views reuse from different locations is presumably not so common so
it may not matter there much, but for adapters and anything else used
from content objects this becomes tricky otherwise.

> >I mean, naively thinking I think it should
> >be possible to use (call a method on) an object without having to 
> >worry about how this object interacts with other objects. I'd call
> >this use.
> 
> Right, but somebody has to worry about it. Whoever introduced that component
> into the system should have arranged for the other components it needed.

But I thought that exactly this cannot really be done in this case.
If the context=self pattern is used a lot it might be done, but 
if you're just *assembling* components you have no control over this.
And if it's not used, the component assembler cannot decide for
instance that a certain service uses a RDB backend by plugging in the
right component for this. Unless the component assembler has complete
control over the whole system, that is, but presumably we have different
sites in a system in part for the reason that there may be multiple
independent component assemblers (still working together).

> >Hm, I'm reasoning from the case where I, the author of components, also 
> >have
> >an idea of how they're assembled. In fact, I may be actually writing
> >an application, worrying about assemblages and so on.
> >
> >I am also assuming that some other area of the application is created
> >and assembled by someone else. Now I want to interact with this other
> >area. There are multiple author/assemblers. 
> >
> >>From the pure assembler point of view.. Imagine I have this assemblage
> >of components. Now I want to hook up one component to another component
> >which is in someone else's assemblage. In your model my context matters, so
> >this would mean that I would need to replicate a version of this other
> >assemblage in my own assembly before it all works. Is that a correct
> >interpretation?
> 
> I suppose so. But if you are using the other assemblage, doesn't it already
> have one it needs for it's own requirements?

I don't understand here what you are referring to by saying 'doesn't it
already have one'? One context? I thought was is not possible for this
other assemblage to use its own context when I call into it from
another site, at least not without altering its code.

> You'd be typically building a
> single site by composing these and other assemblages.

I'm not sure what this means. Where are these assemblages coming from?
We have one site, so one assemblage?

> >Imagine there's a site X, which contains objects. It somehow has a need
> >for a count of those objects, and looks up a service which maintains this
> >count.
> >
> >Now I have a site Y, which uses facilities in site X by calling into
> >it. I have to supply a version of the counting service in site X. But
> >this version of the service won't have the correct count.
> 
> So you are accessing some facility that depends on the count.  So, let's
> say the job of this facility is to generate a count report.  There are
> 2 possibilities:
> 
> 1. The facility generates a count report for the place it's used.
>    In that case, it will report Y's count and it's doing it's job.

X needs the count, not Y, and X will get screwed up if the facility reports
Y's count. Y is not using the count at all directly. Y's just using X.

> 2. The facility generates an "X count report". That is, it's job is
>    to report specifically on the count in X. Well, in that case,
>    the facility had better supply a specific context when it gets
>    the count service so that it gets the right one.

Can't this lead to lots of confusion and misunderstanding? It seems to
me such a data dependency is fairly easily introduced and supplying
the context to be self is easily forgotten. When testing the thing
even works. It's just that when you reuse X from somewhere else that
it starts failing.

Regards,

Martijn




More information about the Zope3-dev mailing list