[Grok-dev] Re: Grok nomenclature
Martin Aspeli
optilude at gmx.net
Wed Apr 30 17:48:00 EDT 2008
Martijn Faassen wrote:
> Martin Aspeli wrote:
> [snip]
>> The point is that we need a convention that's (a) visually appealing (b)
>> clear and (c) consistent, so that we don't end up with 100 different
>> ways of doing the same thing, making it hard to figure out what
>> components actually get registered when you work with a complex package
>> with potentially dozens of grokked things.
>
> I think we should investigate a way to signal that we want
> auto-registration for existing classes (that you now register using ZCML).
>
> That is, if you say:
>
> from plone.app.portlets.portlets import base
>
> class MyPortletAssignment(base.Assignment):
> pass
>
> nothing happens. You register using ZCML or not at all; Grok won't care.
>
> If you say:
>
> import grok
> from plone.app.portlets.portelts import base
>
> class MyPortletAssignment(base.Assignment):
> grok.grokked()
>
> It'll be grokked (if a grokker was registered for base.Assignment of
> course). 'grok.grokked()' just adds the IGrokked interface to these
> classes. You then are supposed to use directives where needed.
There's a slight problem with that, in that if you did implements() as
well, it may override, but I'm sure this could be worked around.
How about:
class MyPortletAssignment(base.Assignment):
grok.as('plone.portlet')
This would look up a named grokker called 'plone.portlet' that would be
able to grok this type of class. I would also make it possible to
parameterise this, so e.g.:
class MyPortletAssignment(base.Assignment):
grok.as('plone.portlet', name='my_assignment', for_=IFoo)
In pseudo-code, grok.as() would be:
def as(_grokker_name, **kwargs):
grokker = getUtility(IGrokker, name=_grokker_name)
context = sys._getframe(1)
grokker.grok(context, **kwargs)
This is a fairly fundamental shift, though. :)
> These directives can be defined by grok. In this case the semantics of
> these directives should be the same, or very similar, to the semantics
> of the directives as used in Grok ('grok.context()' should not suddenly
> be used to set the view name, say).
Sure. However, as soon as I needed another descriptor (to set the
portlet manager, say), I'd need to venture outside the grok namespace,
since I couldn't invent grok.portlet_manager('foo') easily. More on this
below.
> Sometimes you need domain-specific directives. Let's imagine you need a
> 'pipeline' directive (purely imaginary), and this is entirely portlet
> specific. Then you'd do:
>
> import grok
> from plone.app.portlets.portlets import base
>
> class MyPortletAssignment(base.Assignment):
> grok.grokked()
> base.pipeline("Whatever")
Right - in the grok.as() example above, I actually imagined descriptors
moving to named parameters to the grok.as() function. To someone not
familiar with the details of what is Grok what isn't Grok, the
distinction between grok.* and base.* would be fairly arbitrary.
However, I think you make a good point about treating these as
domain-specific extensions with their own namespace below.
> It should be clear to the reader of the code that this is a class-level
> directive - there's nothing else it could be doing, and people should be
> able to recognize class directives as they're well familiar with
> zope.interface.implements().
True, it's less of a problem than the base-class case.
> This will allow domain-specific extensions to the Grok language to be in
> their own namespace, and there won't be an explosion of classes, one for
> non-grok and one for grok, where this is not necessary. If ZCML can
> register it, one should be able to register it with Grok too.
That's a very good point - I agree with this meme very much, actually.
Of course, in some cases, it makes sense to have a Grokish base class.
For portlets, for example, we're actually condensing three classes to
one with Grokish behaviour and may want to make that explicit.
> The requirements for extensions to the Grok domain specific language:
>
> * avoid there being a "ZCML class" and a "Grok class". No explosion of
> base classes. Of course if there's no base class at all yet for the ZCML
> case we are fine.
+1
> * clearly signal to the reader of the code that things are being grokked.
+1
> * don't expand the 'grok.' namespace. What's in there is defined by Grok
> (and five.grok follows that). Separate namespaces are a good thing, and
> monkey-patching import namespaces is bad.
+1
> * there being a way to evolve an application from the use of ZCML to the
> use of Grok, without changing everything at once.
+1
> * reuse grok directives where it makes sense
+1
> * introduce new directives where that makes sense, and import the
> directives from the same place as the base classes. I think these things
> should be semantically near.
+0.5 - I think this is clear when it comes to directives, certainly. For
other things (base classes - are there other primitives we need to
consider?), conventions may be useful.
> If this means that you end up importing directives and base classes from
> 10 different modules in a package, I think it's time to start
> refactoring the package and consolidating the places you need to import
> from into one.
True. I imagine us having convenience imports in places, certainly.
Cheers,
Martin
--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book
More information about the Grok-dev
mailing list