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

2009-12-01 Thread Chris McDonough
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. Wha

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

2009-12-01 Thread Tres Seaver
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Martijn Faassen wrote:
> Hi there,
> 
> I'd like to summarize the options I've seen appear in the discussion so far.
> 
> We have the following options:
> 
> 1) introduce a new method, such as "instance()" or "lookup()" on 
> instance. It unifies utilities with adapters. We can make it do whatever 
> we want without worrying about backwards compatibility.
> 
> 2) introduce several new methods that distinguish between utility and 
> adapter lookup. We can make them do whatever we want without worrying 
> about backwards compatibility.
> 
> 3) call the interface, which unifies adapter and utility lookups. Use 
> tuples for multi adaptation. We think could make this work without *too* 
> much backwards compatibility issues (pending research on how prevalent 
> tuple adaptation really is). In the long term we can even map out a 
> deprecation strategy that can smoothly migrate us to a "multi argument" 
> approach.
> 
> 4) call the interface, which unifies adapter and utility lookups. Use 
> multiple arguments for multi adaptation. The backwards compatibility 
> obstacles are largest here as we already have the "default" argument. 
> We'd need to introduce multiple "modes" to selectively upgrade.
> 
> I'm in favor of calling the interface. I'm also in favor of unifying 
> adapter and utility lookup.

+1 to both.  I think #3 is the best overall compromise, perhaps
eventually migrating to #4 after all use of positional default has faded
away.  Making tuple adapter lookup use the non-sugar spelling seems a
pretty low cost.

> On the back end, I'm also in favor of allowing utility creation by 
> factory (or "null adaptation") and allowing instance lookup for 
> instances ("contextual utility lookup" or "adaptation to an instance"). 
>   I think four ways to retrieve an object of the right interface 
> (combining factory/registered instance and lookup globally/lookup for an 
> instance) is a good argument *against* distinguishing between creation 
> strategies or "connection to adapted object or not" in the API.

One easy way to handle this seamlessly is to check the registered
object:  if it implements (rather than provides) the interface, then
call it, otherwise just return it.  Folks who use factories which don't
declare what they implement would need to adjust if we adopt this approach.



Tres.
- --
===
Tres Seaver  +1 540-429-0999  tsea...@palladion.com
Palladion Software   "Excellence by Design"http://palladion.com
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAksVSGwACgkQ+gerLs4ltQ53awCff+U4Pf836NucmWnLCCrvrwul
kC0An3UG6NT51numMPPh78DCqSK9HrJy
=tq4A
-END PGP SIGNATURE-

___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Martijn Faassen
Gary Poster wrote:

> You are leaving out the variants of 3 and 4 that allow calling the
> interface to support multiadaptation, but do not unify utilities.

True, my mistake. Lennart pointed that out too just now.

> My impression is that I am not the only one who is not pleased with
> the proposed unification of utilities and adaptation.

I've tried to analyze why that might be so elsewhere. There are three 
perspectives that I can see:

* everything registered is really a factory. Returning a utility just 
requires registering a special factory.

* everything registered is really an instance. Calling an adapter is 
just looking up an instance and then calling it.

* we have two kinds of things registered, instances and factories. 
zope.component does that today.

> My impression is that we are nearing consensus on the variation of 3
> that does not include utilities.

I could live with that, as long as we had a way to look up utilities on 
the interface too.

Regards,

Martijn

___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Lennart Regebro
On Tue, Dec 1, 2009 at 16:28, Martijn Faassen  wrote:
> * abstract factory not called on an object ("utility factory",
> "null-adaptation")
>
>    In: the requested interface
>
>    Process: look up factory. Call factory.
>
>    Out: a new instance that provides the requested interface

When would you need this? As I understand it, the only difference from
the normal utility lookup is that you don't get singletons. IMO that
breaks the concept of what a utility is, so null-adaption is a better
name for that, but that still means you adapt nothing, so it's not an
adapter either. :-)

> * abstract instance retrieval for an object ("utility associated with an
> instance", "adapting to an existing instance")
>
>    In: the requested interface, one or more instances.
>
>    Process: look up instance with input instances as "context".
>
>    Out: a previously registered instance that provides
> the requested interface

Hmm. Singleton adapters, in other words. I can see that as useful, sure.

-- 
Lennart Regebro: Python, Zope, Plone, Grok
http://regebro.wordpress.com/
+33 661 58 14 64
___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Charlie Clark
Am 01.12.2009, 17:08 Uhr, schrieb Lennart Regebro :

> I'm +1 for 5.

"wot he said" x 10 :-)

The video + audio to scart example struck me last night and providing  
expressive(?) examples of this to match so that one is less easily caught  
by tuples as arguments is a doddle.

cables = (audio, video)
connector = IScart.adapt(cables, "HDTV")

Assuming I haven't got totally the wrong end of the stick this shouldn't  
confuse anyone.

Now, do we have any similar simple but expressive analogy for utilities?  
Soap dispensers?

ISoapDispenser.utility().dispense() # agained, spelled out for clarity  
seeing as that's all the utility does.

I hope my analogies aren't too far off the mark. Helps me a lot not to  
think about what's really going on.

Charlie
-- 
Charlie Clark
Managing Director
Clark Consulting & Research
German Office
Helmholtzstr. 20
Düsseldorf
D- 40215
Tel: +49-211-600-3657
Mobile: +49-178-782-6226
___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Martijn Faassen
Hey,

Chris McDonough wrote:
[snip]
> If you want to create a world where callers never need to care about the 
> lifetime of any object returned by a component lookup, you could also return 
> a 
> proxy wrapper around the returned object that only allows for the invocation 
> of 
> the methods defined in the interface looked up.  Any other access or 
> invocation 
> would raise an exception.
> 
> This would make this worldview 100% consistent, completely documentable, and 
> would cause no confusion during use.  It would thus remove any logical 
> argument 
> I have against it.  I wouldn't be eager to use such a system, but it's 
> totally 
> consistent.

In the Python world interfaces aren't enforced on the language level. 
But we all know that the programmer better beware and follow the 
implicit API anyway.

With zope.interface, we have a tool to make that implicit interface 
explicit.

Static type advocates argue that if you actually shouldn't cheat anyway, 
you should have the language help you in verifying that what you're 
doing is correct.

Dynamic type advocates argue that the developer overhead of typical 
statically typed languages is so big that we'd rather have a bit more 
danger. And sometimes being able to cheat and get away with it is darn 
convenient.

We happen to be using a dynamically typed language. I don't understand 
why this particular situation is so unique that this would require a 
proxy that raises exceptions. If you follow that reasoning, you could 
just as well say the only sane way to use methods in Python is to 
require proxies that raise exceptions around method arguments if the 
input doesn't provide the right interface.

Regards,

Martijn

___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Martin Aspeli
Chris McDonough wrote:

> I am more or less somewhere between -0 and +0

That is a high degree of precision. Maybe we need to start thinking of 
our voting system as a Decimal instead of an int?

Martin

-- 
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Martijn Faassen
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.

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?

[snip]
> The current global API has a modicum "kindness" for maintenance
> developers because we *haven't* unified adapter and utility lookup in
> such a way.  They stand a shot at understanding that the result of
> getUtility usually has "lifetime A" and the result of
> getAdapter/getMultiAdapter has "lifetime B".  If we take out this
> safety belt, I'd lean towards more explicitness rather than less: let
> the caller call the result of the lookup.

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)

zope.component presents a compromise between those positions.

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. :)

Regards,

Martijn

___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Martin Aspeli
Martijn Faassen wrote:

> First a statement about the goal of this discussion. The goal of this 
> discussion is to convince people to unify the lookup API. I wouldn't 
> want to make lookup API improvements depend on improvements to 
> zope.component inspired by the discussion below. I'm in favor of 
> exploring that in a separate project, however.

+1

> * abstract factory called on an object (adaptation)
> 
> In: the requested interface, one ore more instances
> 
> Process: look up factory. Call factory with input instances.
> 
> Out: a new instance that provides requested interface
> 
> * abstract instance retrieval (utility lookup)
> 
> In: the requested interface
> 
> Process: look up instance.
> 
> Out: a previously registered instance that provides requested interface.
> 
> * abstract factory not called on an object ("utility factory",
> "null-adaptation")
> 
> In: the requested interface
> 
> Process: look up factory. Call factory.
> 
> Out: a new instance that provides the requested interface
> 
> * abstract instance retrieval for an object ("utility associated with an
> instance", "adapting to an existing instance")
> 
> In: the requested interface, one or more instances.
> 
> Process: look up instance with input instances as "context".
> 
> Out: a previously registered instance that provides
> the requested interface
> 
> The two latter patterns aren't fully supported. All of them could in 
> principle be emulated using the "look up factory/call factory" pattern.

I think the last pattern can be implemented with a custom adapter 
factory. You'll need custom "retrieval" code anyway, so there's probably 
not much more room for abstraction.

> There are two perspectives on distinguishing adapters from utilities. 
> One perspective is:
> 
> * newly created instance (adapter) versus previously registered instance 
> (utility).
> 
> This perspective informs the "singleton" discussion. I'd say a better 
> way to distinguish adapters from utilities (should we wish to do so) is:
> 
> * arguments into the factory (adapter) versus no arguments into the 
> factory (utility)
> 
> That's inspired by the notion that adapters tend to have some form of 
> abstract "connection" to what they adapt, while utilities do not.

This is certainly true, but does that really inform how we use these things?

To me, I use unnamed utilities for:

  * singletons (as in, one implementation)
  * strategies (as in, I look up some configuration for an algorithm by 
asking the CA for an object providing a particular interface)

I use named utilities for:

   * registries of homogeneous objects (to avoid implementing my own 
registry)

I use adapters for:

   * the adapter pattern (my code expects an IFoo; the client code can 
write an adapter factory to get me one from whatever context it passes in)
   * customisation/specialisation (I look up an adapter to fulfil some 
policy, allowing it to be overridden with more specific adapters)

And a few other variations (such as the "retrieve object" use case, but 
that's very rare and has largely been an implementation detail).

I don't think of these in terms of "how many arguments" the component 
needs. I think of them in terms of various software patterns. And to me, 
an adapter provides the ability to work with different "aspects" of an 
object (adapting it to different interfaces) whilst utilities provides a 
way to get the "current" implementation of a particular service or policy.

I'm very much for consistent APIs, and if we can simplify the registry 
implementation with more shared code, that'd be great. I'm just really 
worried that we try to "simplify" by replacing two concepts we've spent 
ages teaching people, with a single concept that is even more abstract 
and used in even more different ways for even more purposes. You start 
having to use lots of words to disambiguate ("named multi argument 
factory component" == a view). I don't think we win there.

Martin

-- 
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Gary Poster

On Dec 1, 2009, at 8:21 AM, Martijn Faassen wrote:

> Hi there,
> 
> I'd like to summarize the options I've seen appear in the discussion so far.
> 
> We have the following options:
> 
> 1) introduce a new method, such as "instance()" or "lookup()" on 
> instance. It unifies utilities with adapters. We can make it do whatever 
> we want without worrying about backwards compatibility.
> 
> 2) introduce several new methods that distinguish between utility and 
> adapter lookup. We can make them do whatever we want without worrying 
> about backwards compatibility.
> 
> 3) call the interface, which unifies adapter and utility lookups. Use 
> tuples for multi adaptation. We think could make this work without *too* 
> much backwards compatibility issues (pending research on how prevalent 
> tuple adaptation really is). In the long term we can even map out a 
> deprecation strategy that can smoothly migrate us to a "multi argument" 
> approach.
> 
> 4) call the interface, which unifies adapter and utility lookups. Use 
> multiple arguments for multi adaptation. The backwards compatibility 
> obstacles are largest here as we already have the "default" argument. 
> We'd need to introduce multiple "modes" to selectively upgrade.

You are leaving out the variants of 3 and 4 that allow calling the interface to 
support multiadaptation, but do not unify utilities.

My impression is that I am not the only one who is not pleased with the 
proposed unification of utilities and adaptation.

My impression is that we are nearing consensus on the variation of 3 that does 
not include utilities.

Gary
___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Lennart Regebro
On Tue, Dec 1, 2009 at 14:21, Martijn Faassen  wrote:
> Hi there,
>
> I'd like to summarize the options I've seen appear in the discussion so far.
>
> We have the following options:
>
> 1) introduce a new method, such as "instance()" or "lookup()" on
> instance. It unifies utilities with adapters. We can make it do whatever
> we want without worrying about backwards compatibility.
>
> 2) introduce several new methods that distinguish between utility and
> adapter lookup. We can make them do whatever we want without worrying
> about backwards compatibility.
>
> 3) call the interface, which unifies adapter and utility lookups. Use
> tuples for multi adaptation. We think could make this work without *too*
> much backwards compatibility issues (pending research on how prevalent
> tuple adaptation really is). In the long term we can even map out a
> deprecation strategy that can smoothly migrate us to a "multi argument"
> approach.
>
> 4) call the interface, which unifies adapter and utility lookups. Use
> multiple arguments for multi adaptation. The backwards compatibility
> obstacles are largest here as we already have the "default" argument.
> We'd need to introduce multiple "modes" to selectively upgrade.

You missed:

5) Call the interface for adaption, and something else for utility
lookup, with tuples for multi-adaptation.

6) Call the interface for adaption, and something else for utility
lookup, with multiple arguments for multi-adaptation.

7) Do nothing. ;)

I'm minus lots for any unification of adapters and utilities. Since a
utility does not adapt anything, and adapters do, all they have in
common is that they implement an interface. Since in some sense, all
objects implement an interface, we have reinvented the object. That's
going to confuse the heck out of everyone. It's a very bad idea.

If tuple adaption is common, which I doubt, I'm +1 for 2. If tuple
adaption is uncommon, I'm
+1 for 5.

I'm also:

-0 for 6
-1 for 7
-lots for the rest

> If I look up a utility I wouldn't want to care whether it happened to be
> a previously registered instance or a factory created one. If I look up
> an adapter I wouldn't care whether it happened to be a previously
> registered instance either. In fact, returning a previously registered
> instance can be very well implemented using a factory. (In fact, this
> suggests to me we should actually explore implementing instance
> registration in terms of special factories.)

Making it less common to have to keep track on when you need factories
and not would be a definite benefit.

-- 
Lennart Regebro: Python, Zope, Plone, Grok
http://regebro.wordpress.com/
+33 661 58 14 64
___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Chris McDonough
Chris McDonough wrote:
> On the semantics of the change:
> 
> 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'll retract this.

If you want to create a world where callers never need to care about the 
lifetime of any object returned by a component lookup, you could also return a 
proxy wrapper around the returned object that only allows for the invocation of 
the methods defined in the interface looked up.  Any other access or invocation 
would raise an exception.

This would make this worldview 100% consistent, completely documentable, and 
would cause no confusion during use.  It would thus remove any logical argument 
I have against it.  I wouldn't be eager to use such a system, but it's totally 
consistent.

- C

___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Martijn Faassen
Martin Aspeli wrote:

> Can you summarise what you mean by this? The thread is so long...
[snip]
> My brain hurts... examples?
[snip]
> I'm afraid you've lost me. Four ways sounds bad, though. ;-)

I've edited down and clarified what I posted earlier.

First a statement about the goal of this discussion. The goal of this 
discussion is to convince people to unify the lookup API. I wouldn't 
want to make lookup API improvements depend on improvements to 
zope.component inspired by the discussion below. I'm in favor of 
exploring that in a separate project, however.

* abstract factory called on an object (adaptation)

In: the requested interface, one ore more instances

Process: look up factory. Call factory with input instances.

Out: a new instance that provides requested interface

* abstract instance retrieval (utility lookup)

In: the requested interface

Process: look up instance.

Out: a previously registered instance that provides requested interface.

* abstract factory not called on an object ("utility factory",
"null-adaptation")

In: the requested interface

Process: look up factory. Call factory.

Out: a new instance that provides the requested interface

* abstract instance retrieval for an object ("utility associated with an
instance", "adapting to an existing instance")

In: the requested interface, one or more instances.

Process: look up instance with input instances as "context".

Out: a previously registered instance that provides
the requested interface

The two latter patterns aren't fully supported. All of them could in 
principle be emulated using the "look up factory/call factory" pattern.

There are two perspectives on distinguishing adapters from utilities. 
One perspective is:

* newly created instance (adapter) versus previously registered instance 
(utility).

This perspective informs the "singleton" discussion. I'd say a better 
way to distinguish adapters from utilities (should we wish to do so) is:

* arguments into the factory (adapter) versus no arguments into the 
factory (utility)

That's inspired by the notion that adapters tend to have some form of 
abstract "connection" to what they adapt, while utilities do not.

Regards,

Martijn

___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Gary Poster

On Dec 1, 2009, at 9:54 AM, Chris McDonough wrote:

> Martijn Faassen wrote:
>> 

...

> I am also in favor of unifying adapter and utility lookup.  Or at least 
> creating a more normalized API.

I guess it is no surprise that I am in favor of a normalized API but against 
the unification.

> On the syntax of the change:

[...]

I followed vaguely.  This was about unification, correct?

> On the semantics of the change:
> 
> 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.

Again, no surprise that I agree with this and following.

Gary
___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Chris McDonough
Martijn Faassen wrote:
> Hi there,
> 
> I'd like to summarize the options I've seen appear in the discussion so far.
> 
> We have the following options:
> 
> 1) introduce a new method, such as "instance()" or "lookup()" on 
> instance. It unifies utilities with adapters. We can make it do whatever 
> we want without worrying about backwards compatibility.
> 
> 2) introduce several new methods that distinguish between utility and 
> adapter lookup. We can make them do whatever we want without worrying 
> about backwards compatibility.
> 
> 3) call the interface, which unifies adapter and utility lookups. Use 
> tuples for multi adaptation. We think could make this work without *too* 
> much backwards compatibility issues (pending research on how prevalent 
> tuple adaptation really is). In the long term we can even map out a 
> deprecation strategy that can smoothly migrate us to a "multi argument" 
> approach.
> 
> 4) call the interface, which unifies adapter and utility lookups. Use 
> multiple arguments for multi adaptation. The backwards compatibility 
> obstacles are largest here as we already have the "default" argument. 
> We'd need to introduce multiple "modes" to selectively upgrade.
> 
> I'm in favor of calling the interface. I'm also in favor of unifying 
> adapter and utility lookup.
> 
> On the back end, I'm also in favor of allowing utility creation by 
> factory (or "null adaptation") and allowing instance lookup for 
> instances ("contextual utility lookup" or "adaptation to an instance"). 
>   I think four ways to retrieve an object of the right interface 
> (combining factory/registered instance and lookup globally/lookup for an 
> instance) is a good argument *against* distinguishing between creation 
> strategies or "connection to adapted object or not" in the API.
> 
> If I look up a utility I wouldn't want to care whether it happened to be 
> a previously registered instance or a factory created one. If I look up 
> an adapter I wouldn't care whether it happened to be a previously 
> registered instance either. In fact, returning a previously registered 
> instance can be very well implemented using a factory. (In fact, this 
> suggests to me we should actually explore implementing instance 
> registration in terms of special factories.)

I am also in favor of unifying adapter and utility lookup.  Or at least 
creating a more normalized API.

On the syntax of the change:

I am more or less somewhere between -0 and +0 on the idea of presenting a 
unified API as methods of interfaces (call or non-call).  While I don't think 
this idea is the worst idea in the world and it might be better than the 
current global API, I don't think we should *only* do this; similar changes 
should be made to the registry itself.  Code that uses the global API needs to 
do a registry lookup for each usage, so it's slower than code which doesn't. 
If interface methods become available to unify adapter and utility lookup, the 
same sorts of methods should be added to the registry itself for 
performance-sensitive code.  I also believe that code that locates a registry 
explicitly and calls lookup methods on it is easier to understand for the 
maintenance programmer than is an equivalent global API.

On the semantics of the change:

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 am extremely uncomfortable with any situation where:

   class IFoo(Interface):
   pass

   IFoo()

... does not result in any factory invocation.  I hope it's obvious why this is 
the case.

The current global API has a modicum "kindness" for maintenance developers 
because we *haven't* unified adapter and utility lookup in such a way.  They 
stand a shot at understanding that the result of getUtility usually has 
"lifetime A" and the result of getAdapter/getMultiAdapter has "lifetime B".  If 
we take out this safety belt, I'd lean towards more explicitness rather than 
less: let the caller call the result of the lookup.

- C
___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Martin Aspeli
Martijn Faassen wrote:
> Hi there,

Thanks for doing the summarise-and-move-it-on job so well, Martijn. It's 
really important.

> I'd like to summarize the options I've seen appear in the discussion so far.
> 
> We have the following options:
> 
> 1) introduce a new method, such as "instance()" or "lookup()" on 
> instance. It unifies utilities with adapters. We can make it do whatever 
> we want without worrying about backwards compatibility.

I find the idea of trying to conceptually reconcile adapters and 
utilities pretty weird. They are quite different concepts. Searching for 
one over-arching metaphor will probably land us in an even more 
conceptual "applies-to-everything" situation.

I've spent the past few years explaining adapters and utilities to 
people as two fundamental types of components. I'd really rather not try 
to bring it "up" one level to explain something more generic (and thus 
less specific/example-friendly).

I could be convinced otherwise, I'm just saying that I don't see why 
trying to "unify" these two things is important.

> 2) introduce several new methods that distinguish between utility and 
> adapter lookup. We can make them do whatever we want without worrying 
> about backwards compatibility.
> 
> 3) call the interface, which unifies adapter and utility lookups.

If all you mean by "unify" is "more consistent API", then +1. I saw 
other things in the thread related to trying to treat the two as 
different types of the same fundamental thing, which I think we want to 
avoid.

> Use 
> tuples for multi adaptation. We think could make this work without *too* 
> much backwards compatibility issues (pending research on how prevalent 
> tuple adaptation really is). In the long term we can even map out a 
> deprecation strategy that can smoothly migrate us to a "multi argument" 
> approach.

+1, though I think the multi-argument thing is still going to be wrong 
in the future, and won't bring enough benefit for the pain it will 
cause. Even if by then there's no BBB to be concerned about, it's still 
a change, and it still breaks documentation.

> 4) call the interface, which unifies adapter and utility lookups. Use 
> multiple arguments for multi adaptation. The backwards compatibility 
> obstacles are largest here as we already have the "default" argument. 
> We'd need to introduce multiple "modes" to selectively upgrade.

-1 (aka "minus a lot"), as I've said before.

> I'm in favor of calling the interface. I'm also in favor of unifying 
> adapter and utility lookup.
> 
> On the back end, I'm also in favor of allowing utility creation by 
> factory (or "null adaptation")

Can you summarise what you mean by this? The thread is so long...

> and allowing instance lookup for 
> instances ("contextual utility lookup" or "adaptation to an instance"). 

My brain hurts... examples?

>   I think four ways to retrieve an object of the right interface 
> (combining factory/registered instance and lookup globally/lookup for an 
> instance) is a good argument *against* distinguishing between creation 
> strategies or "connection to adapted object or not" in the API.

I'm afraid you've lost me. Four ways sounds bad, though. ;-)

> If I look up a utility I wouldn't want to care whether it happened to be 
> a previously registered instance or a factory created one. If I look up 
> an adapter I wouldn't care whether it happened to be a previously 
> registered instance either. In fact, returning a previously registered 
> instance can be very well implemented using a factory. (In fact, this 
> suggests to me we should actually explore implementing instance 
> registration in terms of special factories.)

Heh, I used the "shared adapter implementation" as an example of custom 
factories in 
http://plone.org/products/dexterity/documentation/manual/five.grok/core-components/adapters

Martin

-- 
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-Dev maillist  -  Zope-Dev@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 )


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

2009-12-01 Thread Martijn Faassen
Hi there,

I'd like to summarize the options I've seen appear in the discussion so far.

We have the following options:

1) introduce a new method, such as "instance()" or "lookup()" on 
instance. It unifies utilities with adapters. We can make it do whatever 
we want without worrying about backwards compatibility.

2) introduce several new methods that distinguish between utility and 
adapter lookup. We can make them do whatever we want without worrying 
about backwards compatibility.

3) call the interface, which unifies adapter and utility lookups. Use 
tuples for multi adaptation. We think could make this work without *too* 
much backwards compatibility issues (pending research on how prevalent 
tuple adaptation really is). In the long term we can even map out a 
deprecation strategy that can smoothly migrate us to a "multi argument" 
approach.

4) call the interface, which unifies adapter and utility lookups. Use 
multiple arguments for multi adaptation. The backwards compatibility 
obstacles are largest here as we already have the "default" argument. 
We'd need to introduce multiple "modes" to selectively upgrade.

I'm in favor of calling the interface. I'm also in favor of unifying 
adapter and utility lookup.

On the back end, I'm also in favor of allowing utility creation by 
factory (or "null adaptation") and allowing instance lookup for 
instances ("contextual utility lookup" or "adaptation to an instance"). 
  I think four ways to retrieve an object of the right interface 
(combining factory/registered instance and lookup globally/lookup for an 
instance) is a good argument *against* distinguishing between creation 
strategies or "connection to adapted object or not" in the API.

If I look up a utility I wouldn't want to care whether it happened to be 
a previously registered instance or a factory created one. If I look up 
an adapter I wouldn't care whether it happened to be a previously 
registered instance either. In fact, returning a previously registered 
instance can be very well implemented using a factory. (In fact, this 
suggests to me we should actually explore implementing instance 
registration in terms of special factories.)

Regards,

Martijn

___
Zope-Dev maillist  -  Zope-Dev@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 )