[Zope3-Users] Re: ZCML, practicality,
purity (was "Excellent perspective...")
eucci.group at gmail.com
Fri Dec 23 11:13:20 EST 2005
On 12/23/05, Shane Hathaway <shane at hathawaymix.org> wrote:
> Jeff Shell wrote:
> > I just believe - heavily - after many of my Zope 2 experiences that
> > configuration as done by ZCML should be as separate from the code
> > itself as possible. If it's going to be in the same programming
> > language, it needs to be made clear what it is, what can be done, and
> > what can NOT be done.
> Ok, but you broke your own rule. Quoting your blog entry :
> zope.component.provideUtility(greyhounds, name='greyhound')
> This code appears at module scope. You've hardcoded the configuration
> of a utility. You did it again with some provideAdapter() calls.
> You're doing configuration the same way Zope 2 does it. You created
> nontrivial side effects that no one can control without changing your
> code. Even worse, this is a public example which I myself promoted! I
> apparently made a mistake. Upon reflection, I realize that your example
> is dangerous and illegal, since it integrates poorly with Zope. You're
> outright wrong and your blog should be shot!
I was not writing a Zope 3 Application Server Application - I had one
utility and three adapters crammed into a make believe module :). In
the second article, I moved those into 'basicConfigure()' functions
anyways. My code used nothing more than zope.component and
zope.interface, and that's all that I was trying to show.
I do believe that the component architecture is and should be usable
without ZCML. But I also believe that large systems such as the full
app server and applications built on the larger Zope framework can
benefit from it.
> Ok, not really. ;-) But this illustrates why the line between code and
> configuration shouldn't be a brick wall. Your example would have been
> much cleaner if you had written a function at module scope where you
> perform all registrations for the module. Then users of your module
> could choose to call your registrations or not.
> ... which is pretty much what you did in a later example, in
> basicConfigure()!  Users can choose to call basicConfigure(), and if
> they don't, they start with a squeaky clean configuration. See, this
> idea is not really mine. *You* configured things in Python code. You
> did it because it's natural and easier to explain. I'm suggesting a way
> to let you write configuration code safely, so that those who follow
> your example don't descend into a Zope 2 mess.
I was also writing an advocacy post (in the first one) at midnight
that was bordering days that nearly dropped me dead from the point of
exhaustion. I wasn't wanting to show endless black magic - "and then I
wave my hands and everything is configured!". I was wanting to show
how two modules - zope.component and zope.interface - could be used
without the rest of Zope (aside from zope.exception, I believe).
> Not long after ZCML came into existence, I invented a way to configure
> using Python code, and I think I posted some examples. I realize now
> that the simple way I did it was wrong. What I'm suggesting now is to
> retain the semantics of ZCML but switch the syntax. It would be
> possible to automate the conversion of all existing ZCML files.
> The XML implementation of Zope configuration is an overreaction to the
> things that went wrong in Zope 2. Configuration in Zope 2 was bad
> simply because there was no consistent method of configuring things.
> Now that we have a fairly complete configuration system and a set of
> conventions, sloppy configuration will no longer proliferate in the Zope
> community, unless the system is too rigid. Your example broke
> convention, with potentially harmful consequences for people who follow
> your example, suggesting the system is currently too rigid.
My example, again, was a single standalone module written on near zero
sleep. It was by the second "example" that it had already grown to be
too big to be configured in-line.
> > I think you could achieve this with Python, but you'd need do document
> > the hell out of it and put in a smart and restrictive system that
> > would ensure that sloppy configuration didn't happen, that the
> > 'configure.py' module was unused by anything but the configuration
> > system, and that the package it was in could be loaded as a Python
> > package/module without the 'configure.py' module (which would have the
> > most requirements on the configuration of the outside system) be
> > ignored or otherwise not "blow up" when trying to register against
> > something not defined.
> Restrictions aren't necessary. If developers are simply told what the
> convention is and why they should follow it, they'll follow it. Again,
> the problem in Zope 2 was that there was no convention for
> configuration, so everyone made one up.
Restrictions help. Or, at the very least, warnings. "warning:
configuration module imported by non-configuration system in ..."
> > Also, I'd like to point out that Python is not the best language for
> > housing a lot of complex configuration data. Perl and Ruby tend to be
> > a lot easier to use here, as the language kindof makes it easier to
> > write fake little mini-languages since they're a lot more free-form
> > syntactically. I'm sure there are others here that remember
> > maintaining nested tuples of tuples of tuples for Zope things like
> > __ac_permissions__. Those were not always easy to read or maintain.
> Hmm. I think Python is actually pretty good for mini-languages,
> particularly because the syntax is simple and well known. Also because
> you get smart editors, debugging, familiarity, etc. for free.
Maybe too many of the 'configuration' modules I've seen done in Python
rely too much on big nested dictionaries and lists. You're not using
much in the way of syntax when configuring. You're either calling a
lot of objects or registering a lot of strings / symbols / objects in
big data structures. There are some constructs, especially in Perl,
that makes entering that data easier (like the 'quoted words'
> > ZCML has the benefits of using zope.schema to define and format the
> > fields used in configuration and turn them into meaningful objects.
> We'd still have that.
> > The ability to use local dotted names: <foo for=".interfaces.IPony">
> > <far class="..zoo.Butterstick">.
> We'd still have that too, if we really want it. An import is a lot
> cleaner, though.
And I think that's where I worry. With ZCML, name resolution happens
very late. This seems to cut down on the problems that I've had with
Zope 2 style configuration. If imports are in the top of the module,
as most developers are used to doing, then they're executed as the
module is imported for the first time. This is why I don't want
'configure.py' to be imported by other code if it can be helped.
I feel I have a lot more control over the order with which things are
configured with ZCML. I'm confident in the behavior of ZCML
configuration code being executed independently of any other code in
the system. I know that if my framework depends on hurry.file that I
can ensure it gets configured before my code.
'import' is better and cleaner, but it's a situation where I worry
about side effects unless the imports are outside of the top level of
these hypothetical 'configure.py' modules.
More information about the Zope3-users