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.
> * 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",
> 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
> 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
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.
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
** No cross posts or HTML encoding! **
(Related lists -