[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 )


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 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 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 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 Lennart Regebro
On Tue, Dec 1, 2009 at 14:21, Martijn Faassen faas...@startifact.com 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 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 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 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
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
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 Charlie Clark
Am 01.12.2009, 17:08 Uhr, schrieb Lennart Regebro rege...@gmail.com:

 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 Lennart Regebro
On Tue, Dec 1, 2009 at 16:28, Martijn Faassen faas...@startifact.com 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 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 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 Designhttp://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 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. What's different in this 
 case?
 
 If I want to index an