[Zope-dev] implementing zope.component 4.0

Martijn Faassen faassen at startifact.com
Mon Nov 30 05:59:18 EST 2009

Charlie Clark wrote:
> So adapters are reduced to type conversion?

Adaptation is "give me something that provides this API for this 
object". Conversion in Python asks the same. Adaption just formalizes 
this and generalizes it. I don't see how it's a reduction.

>> Calling an interface is really very similar to this.
>> The main difference is that we don't use the concrete implementation's
>> factory but that we use the interface that specifies the abstract
>> behavior. That is a difference, but doesn't seem to be a huge step in my
>> mind.
> Thanks for the comparison but it is semantically so different and  
> interfaces can be used for things other than adapters that I disagree. The  
> most common example I know of the syntax is with INameChooser() which  
> brings us back to the differences (real or imaginary) between utilities  
> and adapters.

I don't think it's that different at all semantically if you think of 
it. I think what you're getting at with the name chooser example is that 
adapters are not really used for conversion but for accessing a 
*feature* for an object. This was in fact an old proposed name for 
adapters in Zope 3.

So, with INameChooser you'd like the name chooser feature for a 
container. And "int()" *can* be seen as wanting the integer feature for 
a particular string. But that's not as convincing as the example of len 
in Python. 'len()' asks for the size feature for an object (a list, a 
string, a dict, etc).

The difference here is that with conversion, often the original value is 
considered to be unimportant anymore - once I have my integer I can 
forget my string. That's not the case with len - the original object is 
still there and relevant. With adaptation both patterns exist, but the 
feature pattern is more common.

To step away from adaptation for a bit, I find utility lookups 
interesting to compare with imports in Python. The import statement in 
Python is used to import a single global instance of a particular thing 
(an instance, or a module instance). Implicitly the importing code 
expects the imported thing to fulfill a particular interface. A utility 
lookup does something very similar, except that the interface is made 
explicit and it's more easy to plug in alternatives.

I've toyed around with the idea of turning utility lookup into imports:

from foo.bar.baz import IFoo as foo

would be the equivalent of:

foo = component.getUtility(IFoo)

But unfortunately this idea has some drawbacks:

* how to handle named utilities and defaults?

* I suspect it cannot be easily implemented at all. :)

* most unfortunately, imports are usually done on module-level during 
import time while utility lookups *cannot* be done on module-level 
because during import time the utility registry is not initialized yet.

So in fact we need to do this in two steps: import something for the 
utility during import time, and then during run time do the actual 
utility lookup.

That's exactly what this would do:

from foo.bar.baz import IFoo

def main():
    foo = IFoo()

> It's quite likely that I'm wrong in this but I see great potential using  
> adapters for delegation rather than straight conversion. I have very much  
> come to appreciate the power of this delegation in, say, BrowserViews;  
> even if it did take me several months to understand the multiadapter  
> pattern!

Delegation is indeed a special property that conversion and feature 
patterns in plain Python don't have (unless I missed an example). The 
thing that is returned in plain Python is usually of a type that's so 
well known by the programmer it disappears into the background. With 
adapters this is less common. My proposal hopes to make some of these 
types appear into the background a bit more too, though.

> Because I do, repeatedly, make simple mistakes with the adapter, utility  
> (wrong name, wrong signature) stuff I very much appreciate attempts to  
> simplify and clarify the API. But I will greet them the same poor grasp of  
> the underlying concepts than I did the originals!

I agree that we should *also* work at explaining the underlying concepts 
more and better.



More information about the Zope-Dev mailing list