Fwd: [Zope3-dev] a new zcml directive?

Jeff Shell eucci.group at gmail.com
Mon Mar 13 15:38:14 EST 2006


I wrote this reply earlier but forgot to use 'reply all' instead of
'reply'. Oops. I'm also editing and expanding my remarks slightly from
the earlier.

In short: Python is a good programming language, usually easy to
follow. ZCML is not. Either work really hard at improving ZCML, or
just simplify it. I'm having more headaches and misery with it as time
goes by, and the last thing I need is more and more directives when I
get infuriated by the ones that currently exist.

On 3/13/06, Martijn Faassen <faassen at infrae.com> wrote:
> Marius Gedminas wrote:
> [snip]
> > -1
> >
> > I'd prefer
> >
> > from zope.annotation.adapter import AnnotationAdapter
> >
> > getFoo = AnnotationAdapter(for_=IBar,
>  >                            interface=IFoo,
>  >                            factory=Foo,
> >                            key=FOO_KEY)
>  > # I suppose the key could be optional; you could use a
>  > # dotted interface name by default
> >
> > and then the ordinary
> >
> > <zope:adapter factory=".foo.getFoo" />
> >
> > I think this is exactly the same as Jeff Shell's suggestion, but its
> > 3am, and I'm too tired to read his entire message.
>
> I guess it comes down to the question whether annotations are a basic
> configuration concept, like views, and thus have their own directive to
> register them, or not.

It seems like we just had the debate and decision that ZCML was doing too much.

Yes - I sometimes prefer to see <factory ...> (especially in a class
directive) over <utility provides="...IFactory">. But in general, I
want ZCML to be simple. I hate editing it. The more that I
have to do in ZCML, the less that I want to do it. The less that I
want to keep on using Zope. I have had too many frustrations in recent weeks.

We have a good programming language. We should use it as much as possible.

> In your example, the ZCML doesn't show that we actually are setting up
> an annotation, and it doesn't show for what we're setting up an
> annotation for in the first place either. It's one intrepretation of
> ZCML that it should show these things. The other interpretation of ZCML
> is that its main task is just hooking components into the system.

I'm totally with the second option. I'd rather have the Python code
say that it's an annotation than the ZCML. And I hate having to
duplicate that information. I know that if I'm going to have ZCML say
"provides='...'", I don't need to have 'adapts(...)' in my Python
code. But then I find myself staring at my Python code and going "uh,
what does this class do again?"

I'd rather let the Python code say it. I hate seeing views documented
(and implemented) like this:

class Search:
    ...

No 'implements', no superclass, no adapts, nothing. It means there's
some other file somewhere else that is modifying this classes behavior
that I have to look at and change my internal parsing mode to read and
understand. And since I got bit by this again recently (trying to
subclass from formlib's 'SubPageForm but registered with ZCML as a
viewlet caused my __init__ override to go boom and I didn't know at
that point which signature to implement), my anger with the system has
grown.

> Perhaps we should make explicit which ZCML we want to have, as its
> design can be quite different depending on that choice.

I still appreciate ZCML, but only in its most simplistic form. I think
it's applicable for:

* "I have an adapter and would like to register it"
* "I have a utility and would like to register it"
* "I have a class and would like to apply security options to it and a
couple of other declarations (additional interfaces supported, a
factory, etc)"
* "I have an interface, and I'd like to say that all things that
implement it are things of type x"
* "I'd like to load and configure this package now"

I think ZCML should *and only should* be used to basically register
code to run separately from Python imports. That means it shouldn't be
making new components on the fly. That starts to compound its job. Its
job should be, in my arrogant opinion, saying "Here's some Python code
- an object, a function, a class, whatever - and what it means to Zope
(is it an adapter? a utility? or a class that needs security
restrictions applied and supports common mega-interfaces *like*
IAnnotatable)".

That's very different than automation. The automation is "I have a
thing, or want a thing, that does this: go forth and generate it
dynamically for me." Whether it's an annotation adapter, or an edit
form, or a viewlet, there are now extra objects that don't really
exist in any Python module that can be easily inspected, introspected,
etc. They are phantoms generated by the machine. You have to have them
to make certain things work. But what they are isn't obvious. They
become painful to debug, introspect, etc.

It really seems like one of the goals/ideas for ZCML was that you
could make a crazy application with Zero Python Code - just use a lot
of ZCML and it will generate everything for you. Or use ZCML, an
interfaces.py module with some schema, and have a couple of persistent
classes, and then use all of this ZCML to have the system build
everything for you.

I think that's a terrible idea. It binds you to a narrow view of the
system, and restricts growth opportunities for when you need to do
"just one little thing different". What if this annotations directive
doesn't quite do what I need to do with my annotations adapter? Can I
still use it? If not - how do I then provide annotations? What is this
directive doing and how can I translate that into plain old python and
then register the right thing instead? That's the headache I run into
time and again: there's no path between "this is the easy one line
ZCML way of doing things" (although it's often five lines after some
trials and error) and "this is the slightly harder but will let you do
what you need to do way of doing things that will still work like the
one line ZCML way of doing things when all is said and done."

To me, that feels like the "Z Shaped Learning Curve" re-invented.

So no - I don't want more directives.

A few months ago I defended ZCML pretty staunchly. Today, not so much.
It's becoming the bane of my Zope 3 development experience, causing
more headaches and lost time than it feels like it's helping.

>From "ZCML Needs to do Less", at the very end (proposed guidelines for
new packages):

* Try to reuse as much of the existing Component Architecture concepts
  (utilities, adapters, views) as possible.

* Try not to invent new ZCML directives unless you have a really really
  compelling reason to do so. If you're limiting yourself to utilities,
  adapters, and views anyways (and this should be enough), you shouldn't need
  new directives, the existing once should suffice.

* Don't let ZCML do automation, Python is better at it. People will look for
  some of the behaviour in the Python code only to find out that it's not there
  but hidden behind dubious ZCML directives. This can be avoided. Simply try to
  look at ZCML directives as on/off switches and you're half-way there.

http://www.z3lab.org/sections/blogs/philipp-weitershausen/2005_12_14_zcml-needs-to-do-less

Let my ZCML be like that. I don't want to have to program in it,
please. (And note: my frustrations have nothing to do with ZCML being
XML, or being a configuration language at all. It only has to do with
the automation making things 'easy', which then makes them very very
very hard to work with outside of ZCML because what you learn in one
system does not apply to the other).

--
Jeff Shell


More information about the Zope3-dev mailing list