[Zope3-dev] Re: ZCML bad ;-)

Jim Fulton jim at zope.com
Sun Jan 22 10:58:43 EST 2006


Jeff Shell wrote:
> On 1/20/06, Shane Hathaway <shane at hathawaymix.org> wrote:
> 
>>Chris Withers wrote:
>>
>>>FWIW, I still hate ZCML for the following reasons:
>>
>>Everyone seems to agree on the direction suggested here:
>>
>>http://www.z3lab.org/sections/blogs/philipp-weitershausen/2005_12_14_zcml-needs-to-do-less
>>
>>I think that will resolve a lot of concerns.

...

> But I'm really starting to get frustrated with a lot of the elements
> in the ZCML browser: namespace. They do a lot behind the scenes and
> maybe that's a good thing for new users to minimize the amount of code
> they have to write or provide, but it gets frustrating (at least, it
> has for me) when you start growing up beyond that.

To a large extent, they were failed experiments. Just stop using them.

> Maybe the big base-class-mess of Zope 2 made it desirable to not even
> require a base class for a Zope 3 view?

No, that was not the motivation.

 > Some of those viewmeta
> directives are doing a lot of crazy dynamic class and method creation
> to provide IBrowserPublish, traversal to the default view, or
> rendering a certain attribute or template automatically as the
> default. As I was starting to use Zope 3 in earnest, I wouldn't
> understand when I should use browser:page versus browser:view, and if
> I did browser:page with both a template and a class if there was any
> way I could refer to the template from the class's methods since the
> template was stitched in by ZCML.

The management of templates was the reason we had to go down this road.
Some influential early Zope 3 reviewers (who will remain nameless to
protect their reputations :) complained that they didn't like to muck
up their Python code with template definitions.  They didn't like
seeing things like:

   foo = ViwPageTemplateFile("foo.pt")

in their Python code and prefered to relegate those definitions to
ZCML.  This was the origin of the page directives.  In retrospect,
it was a mistake.

The fact that we have both view and page had to do with an early
concept, multi-page-views that also hasn't terned out to remain useful.

Again, I'd be happy to see these directives fade from use.

> Even though I've made a pro-ZCML case on the basis that most of the
> directives and their attributes are reasonably well documented, what
> the directives DO is another matter entirely. In theory, registering a
> view is equivalent to zope.component.provideAdapter((ISomeObj,
> ISomeSkinLayerOrRequest), provides, name). But the directives do so
> much more than that. So while I'm often trying to stick with apidoc
> for reference, I'm always going into Zope to see how things really
> work and usually to ensure that I'm really doing things correctly. And
> looking at some of the metaconfigure code is... Well, it's rough.
> There's something defined in zope.app.publisher.browser.menumeta for
> menuitems called 'extra'. I've been struggling to find out if I can
> add things to menu items to render out like javascript onclick
> handlers. And I mean s-t-r-u-g-g-l-i-n-g. I finally find this 'extra'
> thing. It's not defined in any schema interface. What is it? What form
> does it take? It's in the argument list in the directive handlers, but
> not in the metadirective's schema. Should I write my own menu system?

This is a very good example.

> I like being able to declare menus in ZCML - keeps their order easy to
> control. But I don't want to be writing javascript handlers in it. I
> don't want to be writing new directives. I've been crawling through
> this code all morning. It's very convenient until you can't do what
> you want... So then the issue becomes "should I just do it in Python?

Yup.

> Is there a way I can do it but still have it all work out nicely at
> configuration time?

I think so.

 > I'm guessing there is if I write a custom
> IBrowserMenu utility and write my own way of providing menus to it..."

...

Menus are an idea that, like the rest of the component architecture, has evolved
and simplified over time.

========================================
Menus are best understoood as a pattern!
========================================

The pattern goes like this:  A menu us just a collection of
named components that provide some interface.  The menu is the
menu item type.  To define a new menu, define a new type.
To make the menu items context sensitive, look up the menu
items as adapters.  (Well, you typically do that anyway, since
menu items generally adapt at least the request.)  How you
display or order the items is up to you.

That's it.  Simple.  For our applications, we often create
mini menu frameworks to meet specialized needs.  The existing
menu interfaces, including the ZCML directives implement this
simple pattern.  Sadly, things designed to make things simpler
often take simple ideas and make them complex. :)  The original
menu framework didn't implement this pattern, but was retrofitted
to do so.

If you want to define menus or menu items in Python, go ahead.
Just define interfaces and adapters and register the adapters
in ZCML.



> I like the approach taken in zope.formlib, which puts more trust in
> the Python code and provides good but also simple / shallow base
> classes (which aren't required, they just provide a lot of the common
> functionality). Trying to do some custom forms with
> zope.app.form.browser's forms in Zope 3.1 was challenging. Doable, but
> challenging, especially as zope.app.form.browser's forms really wanted
> to be built by ZCML. It's still very nice in theory from the "naked
> objects" "scaffolding" "auto-admin" perspective: build add forms and
> editforms automatically in 6 lines of ZCML! No programming required!
> But the difficult step always comes when it's time to do just a bit of
> programming from that, and then a bit more, and then a bit more. And
> then you might think you provided a new custom form base class you can
> use all over the place and get its template, only to find that ZCML
> wrote over it for the subclass.
> 
> So I was happy to see zope.formlib, and to not see any meta.zcml
> anywhere in that package.

Yup. BTW, did you notice formlib/page.txt?

... Lots of interesting stuff snipped

> I really think that the core of the Zope 3 component architecture is
> beautiful. I had that zen moment recently where I went "oh, it's all
> adapters, utilities, and multi-adapters!"

We had that same zen moment a few months before 3.0. :)


 > When I stay the closest to
> it - writing code that uses adapters to turn a list of schema fields
> into something nice for file system representation and back - I'm
> really happy with Zope 3. When I'm writing core content classes and
> basic adapters (INameChooser, ISearchableText, IReadFile/IWriteFile)
> and it all just works, I'm happy. Even when I'm using ZCML to register
> classes, security, adapters, and some extra marker interfaces, I'm
> pretty happy (but it does start to tear at me - "how much or how
> little should I declare here?").
> 
> But these days, when I'm working in my browser/configure.zcml type
> files, I get real grumpy, real quick. That's become the part where I
> kindof close my eyes and hope I get everything right.

OK, so you know the way to proceed. :)

> Zope 3 should dominate not only quick'n'clean,

I'll note in passing that we won't be quick enough until we
provide an alternative to the "object file system" and make people
understand that, while it is often useful, it isn't necessary and
can make things harder.  Many people have figured out how to use
Zope without the ofs, but there isn't an easy out of the box easy
way for people to do it.  My Bobo project was aimed at that,
but, sadly, I haven't had time to pursue it.

 > but
> quick'n'clean'n'grown-up - an architecture that's closer to the scope
> of a J2EE type system, that brings a lot of powerful concepts into
> Python without a lot of complexity and without being cavalier with the
> language, can handle complexity as well as simplicity, and is governed
> by a few basic principals that we believe give plenty of benefits.
> Interfaces/Schema combined with a few helper functions empower design
> by contract without being restrictive or unpythonic, and that contract
> alone can be used for so many things: web form generation and
> validation; SQL generation, validation, and import; XML import/export;
> documentation; RPC formatting; and of course - adaptation (duck typing
> on steroids).

Yup.

> And I think that unless ZCML is simplified and starts doing less
> automation as promoted by Phillip, that message will be lost.

Fortunately, this trend is underway.  I think your articulate
essays are helping a lot!

 > Again -
> I like what zope.formlib offers, and I like the IFormAPI interface and
> concept. I'd like to see more of a move in that direction for the core
> facilities. Instead of "write these n lines of ZCML to auto-generate
> an edit form for a schema/interface", it should be "write these 5
> lines of Python to generate that form, and 1-2 lines of ZCML to
> register it, name it, and protect it." And then, as the user may need
> to customize the form, they can add to this class instead of having to
> span the two worlds of ZCML automation and Python. It's much easier to
> go up a good and simple base class tree and read / understand the code
> than it is to go through ZCML meta configurations. And it makes the
> distance between the main doctest documentation and how things work a
> lot shallower.

Well said.

Perhaps we should start actively deprecating many ZCML directives?
This will require some volunteer effort to do it well.

Jim

-- 
Jim Fulton           mailto:jim at zope.com       Python Powered!
CTO                  (540) 361-1714            http://www.python.org
Zope Corporation     http://www.zope.com       http://www.zope.org


More information about the Zope3-dev mailing list