[Grok-dev] concerns about grokcore.component.provides

Leonardo Rochael Almeida leorochael at gmail.com
Wed Sep 9 10:33:18 EDT 2009


Hi,

IMO, Adapters are one compliated beast, semantically speaking.

To throw some more wood into the fire, though not necessarily helping,
for me it helps to differentiate between the adapter and the
adaptation.

In the Zope Component Architecture, IIUC, an adapter is a callable to
which you feed an object of one kind (interface), and get an object of
another kind in return.

In this sense, classes registered as adapters are, at the same time, factories.

Meanwhile, the instances of an adapter class are the things which we
expect to provide the interface we're currently declaring with the
"provides" directive. So in this sense, the instances are not the
adapters, but merely the result of the adaptation.

If the adapter where to be a function instead of a class, the result
would be the same, the function is the adapter that takes the adapted
object as argument and returns an adaptation, which we then expect to
provide a certain interface, no matter what kind of interfaces the
adapter-function provides (usually none).

Thinking about this. IMHO, one syntax that would be clean enough for
my tastes would be:

class MyFunkyAdaptor(NotNecessarilyGrokAdapterOrSubclass):
    implements(IDestinationInterface, IAnotherInterface)
    grok.adapts(from_=ISourceInterface, to=IDestinationInterface)

Notice this same syntax could be used with functions that act as adapters.

@grok.adapts(from_=ISourceInterface, to=IDestinationInterface)
def MyFunctionAdapter(source_obj):
    ....

Cheers, Leo

On Wed, Sep 9, 2009 at 16:02, Martijn Faassen<faassen at startifact.com> wrote:
> Hey,
>
> Gary Poster wrote:
> [snip]
>> However, I'm also more convinced that the name of
>> "grokcore.component.provides" is a problem.
>
> I agree it's a problem, as this isn't the first time it came up.
>
>> My current preference is
>> for "provides_adapter".  Reading this, I understand what the grok
>> directive is doing.
>
> One issue with this naming is that grok.provides is also used for global
> utility registration right now. You'd also need a grok.provides_utility
> that does the same. The principle is to reuse directives if they do
> something similar enough, which one argue (also from the underlying
> code) is the case here.
>
> I also think there's a bit of a DRY violation in saying
> provides_adapter. The base class indicate it's an adapter. The
> directives specify how it's an adapter. In your example you have your
> own base class (CookbookTopLevelObject) that obscures this somewhat. One
> needs to trace base classes. But this is a fairly common thing an object
> oriented developer needs to do anyway, and it won't be long before they
> realize it's an adapter.
>
> (this is an argument for a different-style martian that allows one to
> indicate what is being registered not by base-class but by directive:
> grok.adapter(), grok.view(), etc. That's another discussion and a much
> bigger topic, though)
>
> We still have the confusion of the word provides, which in ZCML means it
> provides an *interface*. I guess here it would mean "provides an adapter
> of kind IFoo".
>
> Let's think about naming some more. We're writing a class. It implements
> some interfaces. We now want to look up an instance of this class. We do
> this by asking for an instance that provides one of these interfaces. In
> cases of adapters, this instance is created on the fly, in case of
> utilities, it's been registered already.
>
> So what do we call: "this class makes instances that will provide
> interface X when looked up as an adapter/utility" notion?
>
> Let's check the thesaurus.
>
> The class is a factory for IFoo adapters (or the IFoo utility).
> Therefore, we could consider grok.factory(IFoo). There's a slight
> overloading with the factory notion in Zope 3 (there's such a directive,
> I think?), but it doesn't appear to be a commonly used notion (and
> certainly not in Grok). Also I have the feeling there's a subtle
> difference between the way grok.context and grok.layer are used and
> grok.factory, but perhaps that's just me.
>
> The class creates IFoo adapters (or the IFoo utility). Therefore, you'd
> write grok.creates(IFoo).
>
> Other possibilities might be grok.delivers or grok.produces.
>
> Right now, I think I like 'creates' the best.
>
> [snip]
>> If you do a "from foo import bar" style (still advocated in some
>> quarters, and used at Canonical)
>
> [I tend to do quite a lot of this too. I don't buy the arguments for
> repeating.a.dotted.name.everywhere; in my experience it produces more
> cycles (and needs for deferredimport) than a few 'from foo import bar'
> in a package. Especially when you create a clean interface in a
> package's __init__.py which I really like]
>
>> then the distinction is even more
>> stark, in my opinion.  Current:
>>
>> class FeaturedCookbookLink(CookbookTopLevelObject):
>>      """A link to the currently featured cookbook."""
>>     implements(ICookbookObject, ITopLevelEntryLink)
>>      provides(ITopLevelEntryLink)
>
> For grokcore.component, I'd recommend doing this:
>
> import grokcore.component as grok
>
> (or: from grokcore import component as grok)
>
> [Inside a package, I often use the pattern where I import a module
> instead of an individual name. still a from import]
>
>> My read: huh?
>>
>> Proposed:
>>
>> class FeaturedCookbookLink(CookbookTopLevelObject):
>>      """A link to the currently featured cookbook."""
>>     implements(ICookbookObject, ITopLevelEntryLink)
>>     provides_adapter(ITopLevelEntryLink)
>>
>> My read: ah so!
>
> What do you think about:
>
> class FeaturedCookbookLink(CookbookTopLevelObject):
>     grok.implements(ICookbookObject, ITopLevelEntryLink)
>     grok.creates(ITopLevelEntryLink)
>
> Regards,
>
> Martijn
>
> _______________________________________________
> Grok-dev mailing list
> Grok-dev at zope.org
> https://mail.zope.org/mailman/listinfo/grok-dev
>


More information about the Grok-dev mailing list