[Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0

Chris McDonough chrism at plope.com
Tue Dec 1 12:27:23 EST 2009


Martijn Faassen wrote:
> Chris McDonough wrote:
>> Personally I think that it's a fantasy to believe that the difference between 
>> an object created via a factory on-demand and an object simply returned should 
>> *never* matter to a caller.  You may not want the caller to need to care, and 
>> it may be inconvenient to take into account circumstances where the caller 
>> needs to care.  But because this is Python, the caller still often does need to 
>> care.
> 
>> The only circumstance where a caller would *never* need to care would be when 
>> the object returned could be guaranteed to *never ever* have any methods called 
>> on it that weren't part of the interface defined by the interface being looked 
>> up.  If we want this, we should probably just be using Java.
> 
> I think it's okay for us to say: if you call a method on something that 
> you retrieved by interface that isn't actually specified to be on that 
> interface, you're on your own. It may work, but it's not specified to 
> work by the system you're using.

Let's use an analogy here.

You are a member of a club.  This club is very inclusive, but it has a fairly 
rigid set of protocols that members are expected to follow.  For example, when 
you enter the front door, you are expected to touch a statue next the the door. 
  When a bell rings, you are expected to sing the club song.  At precisely 1pm, 
everyone must kneel in place.  A number of other arbitrary actions are required 
of a new member, and new ones are added every so often.

This club is slightly superstitious, so it is believed that *not* performing 
the required actions is bad luck, and any member who does not perform them "to 
the letter" will bring a pox upon the club and all its other members.  In fact, 
the club members have incontrovertable evidence that this is so.

The club currently has a membership in the hundreds.  They want to be 
inclusive, so they welcome anybody, and they're glad to get new members.  But 
those who come in are expected to read a slightly tattered printout of a 
PowerPoint presentation hanging from a string on the inside of the front door. 
  This printout contains all the known actions that a member must perform in 
response to cues to be a member in good standing.  New members can also ask 
existing members for help, of course, and they can go visit the printout any time.

If everyone follows the set of instructions in the powerpoint document to the 
letter, everything runs swimmingly.  But the powerpoint document is missing 
some pages, (some new cues were added recently) and even if it wasn't, new 
members would almost always have a hard time getting it *all* right on the 
first try because there are a lot of cues these days.  The bell rings, they 
kneel.  They sing the song at the wrong time.  Sometimes they just don't know 
what to do, so they do nothing.

The club also has a wait staff.  Currently the wait staff is not expected to 
enforce any of the rules; they simply keep things running.  They are severely 
underworked at the moment.

Currently the club interpersonals are a little broken: when a new member has 
the wrong response to a cue, the existing club members might try to help that 
new member, but often they just complain to each other about the offending new 
member.  Some members just claim "I've already paid my dues to be a member 
here, he should too."  Other members try to write more little sticky notes and 
hang them up as cues to new members, but nobody is really "responsible" for 
teaching new members the rules.  It's sink or swim, and often new members sink.

If the the "club" is the "ZCA community", the "cues" are the worldview that 
says that the ZCA is by god a way to convert one interface to another and that 
utility and adapter lookups are no different than each other, the wait staff is 
the ZCA itself, new members are new developers, and the mistakes they make when 
not following the cues using methods of the adapted objects that aren't defined 
by the adapter interface:

1) Put the wait staff in charge of helping new members.  This is analogous
    to making the ZCA throw (or at least warn) about errors that new developers
    make by using attributes and methods of an object not defined by the
    interface returned by an adapter or utility lookup.

2) Get rid of most of the cues.  This is analogous to "unifying" adapter lookup
    and utility lookup by making the *caller* responsible for doing "adaptation"
    by calling the result of the lookup himself.

Or do nothing.  Doing nothing is wrong because at some point *we* become 
maintainers of code written by folks that "didn't get the jokes" of the ZCA 
worldview.  So we can either take the joke out or make the joke impossible to miss.

> I'm not sure why lifetime issues are considered so important here. Of 
> course they sometimes matter. But we use ORMs all the time. We create 
> traversal hierarchies on the fly all the time. What's different in this 
> case?
> 
> If I want to index an object, do I care whether the catalog was just 
> created on the fly and it's talking to a relational database?
> 
> I think you're arguing that because abstractions are sometimes leaky 
> (lifetime issues) we shouldn't have this abstraction at all. Why is the 
> leakiness so important here?

*This* abstraction is leaky.  Other ones which have been proposed are not.  Or 
at least not as.

> I think there are two centers of attraction for unification:
> 
> * everything is a factory. If I want to look up an instance, I look up a 
> factory that returns me the same instance all the time. I.e. IFoo() and 
> IFoo(a)
> 
> * everything is an instance. If I want to call a factory, I look up an 
> instance that is a factory, and call it. I.e. IFoo.lookup() and 
> IFoo.lookup(a)(a)

I think either of these positions is probably consistent.

> zope.component presents a compromise between those positions.

I don't know that the documenting the compromise as a worldview is particularly 
useful, given that any reasonable Python programmer can add back the compromise 
abstractions with about 10-20 lines of his own code should he want to.

> The advantage I see of unifying towards factories is a less verbose API 
> for common operations than an explicit API would have.
> 
> If you take the utilities come from a factory approach, this would 
> suggest an API like this (on Interface):
> 
> def __call__(self, arg=()):
>      if not isinstance(arg, tuple):
>          arg = (arg,)
>      return self.factory(arg)(*arg)
> 
> # low level
> def factory(self, arg=()):
>      return registry.lookup(from_=arg, to=self)
> 
> The drawback is that while you *can* register utilities as non-factories 
> and look them up, you'd do it through 'factory', as the real way to look 
> up utilities would be to call a factory.
> 
> If you take the utilities are registered instances, that would suggest 
> an API like this:
> 
> # convenience
> def __call__(self, arg=()):
>      if not isinstance(arg, tuple):
>          arg = (arg,)
>      return self.lookup(arg)(*arg)
> 
> def lookup(self, arg=()):
>     return registry.lookup(from_=arg, to=self)
> 
> You'd register utilities as instances directly and look them up using 
> lookup(). The convenience method still works for adapters.
> 
> The drawback is that IFoo() would result in IFoo.lookup()(), and calling 
> the utility would make no sense.
> 
> The implementations are the same, but the semantics are quite different. :)

I will try to understand this more later.

- C



> 
> Regards,
> 
> Martijn
> 
> _______________________________________________
> Zope-Dev maillist  -  Zope-Dev at zope.org
> https://mail.zope.org/mailman/listinfo/zope-dev
> **  No cross posts or HTML encoding!  **
> (Related lists - 
>  https://mail.zope.org/mailman/listinfo/zope-announce
>  https://mail.zope.org/mailman/listinfo/zope )
> 



More information about the Zope-Dev mailing list