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

Gary Poster gary.poster at gmail.com
Tue Sep 1 20:52:03 EDT 2009


Hi all.

The Launchpad team successfully made its first foray into grok land  
today by switching some of lazr.restful to use it.  It has turned out  
nicely so far, and the next step is to make some custom martian  
declarations.  Thank you!

In the course of this, though, we came to a couple of concerns about  
grokcore.component.provides that I'd like to share.  I understand why  
the decisions have been made the way they are, but I'd at least like  
to share our thoughts.

Consider this only slightly contrived snippet, which is an example of  
what you find repeatedly in our code with the new change:

class FeaturedCookbookLink(CookbookTopLevelObject):
     """A link to the currently featured cookbook."""
     zope.interface.implements(ICookbookObject, ITopLevelEntryLink)
     grokcore.component.provides(ITopLevelEntryLink)

First, as an old Zope 3 hand, I personally find the name  
grokcore.component.provides very confusing.  For the zope.interface  
package, of course, "provides" describes what an instance directly  
offers, while "implements" describes the special case of what a class  
produces.  I suspect the word "provides" was chosen for the  
grokcore.component package because it mirrors the zcml registration of  
an adapter.  However, in context, I find it very confusing, especially  
juxtaposed with the "implements" call.

Second, this looks an awful lot like a DRY "violation"--one of the  
things I thought grok was particularly trying to avoid.  Shouldn't you  
be able to make a single spelling for the class, simultaneously  
declaring that the interface is implemented and that it should be  
registered as such?  In other words, shouldn't this be equivalent to  
the above?

class FeaturedCookbookLink(CookbookTopLevelObject):
     """A link to the currently featured cookbook."""
     zope.interface.implements(ICookbookObject)
     grokcore.component.provides(ITopLevelEntryLink)

I can grudgingly acknowledge an edge case of wanting to be able to  
register an object for an interface that it does not implement, but  
what an edge case!  You want to make a promise one way, but carefully  
avoid making the promise another?  Declaring that a class implements  
an interface is as much a matter of good faith as registering an  
adapter--nothing is actually verified, unless you explicitly ask for  
that.

I suppose it would be reasonable to allow someone to continue to spell  
this edge case--you can in zope.interface/zope.component alone,  
certainly--but I think that the best advertised spelling should

My main goal is to see if I can make someone--say, eventually,  
Martijn ;-)--agree with us, and change things a bit.  However, I feel  
like I'm whining if I complain without trying to offer a solution, so  
I'll try to make a couple.  I'd be thrilled if someone else agreed  
with our concerns, but came up with a better solution.

Option 1: you ignore my concern about naming, and just address the DRY  
violation.  grokcore.component.provides will automatically add the  
interface to the class, so my second, theoretical example does in fact  
produce the same thing as the first.  Perhaps you add a flag or  
another function that has the current behavior of not adding the  
"implements" declaration.

Option 2: "grokcore.component.provides" is deprecated in favor of  
"grokcore.component.instancesProvide".  The new declaration has the  
behavior I describe in option 1.  It would result in this:

class FeaturedCookbookLink(CookbookTopLevelObject):
     """A link to the currently featured cookbook."""
     zope.interface.implements(ICookbookObject)
     grokcore.component.instancesProvide(ITopLevelEntryLink)

Thanks again for grokcore/martian.  They have given us a nice win, and  
we're interested in looking at them more.

Gary


More information about the Grok-dev mailing list