[Zope3-dev] alternate format for configuration files

Jim Fulton jim@zope.com
Sat, 23 Mar 2002 02:48:26 -0500


Jeremy wrote:
> 
> I've been noodling with a different way to write Zope3 configuration
> files, and I'd like to get some feedback.
> 
> We had a Sprint this week were PythonLabs & friends spent some time
> writing a simple product.  It was the first time I really looked at
> the .zcml files and tried to understand what they do.  I found a few
> things difficult:
> 
>     - There is a lot repetition in zcml.  I often type the same name
>       over and over again.  Fred showed me how to use an XML entity
>       reference (a macro) but that doesn't seem like a good solution.

Stephan and Barry suggested allowing a leading dot imply the include file's
package, rather than ZopeProducts. I think that this would address the
repetition issue.
 
>     - The names of tags don't have obvious meanings.

I have a hard time with this comment. Are your proposed names
more obviously meaningful? You use the *same* name for views.
 
>     - There is no structure to the configurations.  It's just a
>       sequence of directives at the same level and in an arbitrary
>       order.  We found that we had many duplicate entries in different
>       files, because there was no obvious place to put some things.


This is necessary to allow overriding and augmentation. It is critical that
people be able to easily change configuration provided by a product 
without changing the product's configuration file.  For example, it's
important to be able to replace views in separate configuration files.

A single hierarchy for a component is just not an option.

>     - I think that the use of attributes makes for a lot of extra
>       punctuation that is hard on the eyes.  This, of course, is a
>       very subjective thing.

Yes. I think that use of elements adds far more noise.
 
> I find that EJB deployment descriptors, which are also based on XML.
> I like these descriptors better because they are organized
> hierarchically.  All the directives pertaining to a particular entity
> bean are contained within the entity bean's top-level tag.

I need to look at these, however, a strict hierarchical organization
won't meet out goals of being able to easily modify a configuration
through overriding and augmenting configuration in separate files.

> The use of hierarchy means that redundant typing is avoided

Yes.

> and that the names can be simpler and easier to understand.
 
I don't see this.


> I've also made the simplifying assumption that a Python dotted path
> name is relative to ZopeProducts when it's used inside a Product
> directive.

This would make sense if:

  - A leading dot (or some other puctuation) was required, otherwise, 
    you couldn't refer to something in a different package.

  - The product element specified a prefix.
 
> I've included two files below.  The first is my proposed new syntax.
> It's a rough cut.  I probably have the hierarchy wrong and I may not
> being doing the XML right.  The second is the existing zcml it's based
> on.
> 
> Any comments?  Is it worth pursuing this approach?

I think it's worth considering how to simplify configuration.

It would be interesting to analyze your example a little to compare it
to the current syntax.

 
> Jeremy
> 
> <Zope>
> <Product>

What does the product element add over the Zope directive?
Is there a use case for using product names as descriptions.

>     <Name>JobBoard</Name>
>     <Description>
>         A JobBoard is a moderated collection of job postings.
>     </Description>

If I needed product name and description for anything, which we currently
don't, I would much rather store them as attributes of the Product or Zope
elements, as they are meta-data. As you've given them, they are peers
of Interface and Content, which doesn't seem very clear to me.


 
>     <Interface>
>         <Class>JobBoardEx.IJobList</Class>

Interfaces are not classes.

 
>         <View>
>             <Type>Browser</Type>

Type is an interface, Zope.Publisher.Browser.IBrowserPublisher.
We avoid saying this in zcml providing a separate directive in the
browser namespace.


>             <Name>traverse</Name>
>             <Factory>JobBoardEx.JobList.JobListTraverse</Factory>
>         </View>
> 
>         <View>
>             <Type>Browser</Type>
>             <Default/>
>             <Name>summary</Name>
>             <Factory>JobBoardEx.JobList.JobListTraverse</Factory>
> 
>             <Protect>
>                 <Permission>Zope.Public</Permission>
>                 <Methods>index, getApprovedJobs</Methods>
>             </Protect>
>         </View>
> 
>         <View>
>             <Type>Browser</Type>
>             <Name>NewJob</Name>
>             <Factory>JobBoardEx.NewJob.NewJob</Factory>
>             <Protect>
>                 <Permission>Zope.View</Permission>
>                 <Methods>index, preview, waiting, getJobView, cancel,
>                     home, submit</Methods>
>             </Protect>
>         </View>
> 
>         <View>
>             <Type>Browser</Type>
>             <Name>ApproveJobs</Name>
>             <Factory>JobBoardEx.ApproveJobs.ApproveJobs</Factory>
>             <Protect>
>                 <Permission>Zope.View</Permission>
>                 <Methods>index, cancel, submit</Methods>
>             </Protect>
>         </View>
>     </Interface>

You only showed views. You used the interface to group views that used the
same interface, This didn't really save that much. 

How would you handle adapters, that both use and provide interfaces?
How about utilities, which use interfaces.

I considered this sort of grouping for ZCML and didn't find it to be very 
helpful for the contact example.

You got a little simplification by roling the security assertion into the
view, but not as much as one might have expected.

 
>     <Content>
>         <Name>JobList</Name>
>         <Class>JobBoardEx.JobList.JobList</Class>
> 
>         <ZMI-Factory>
>             <Permission>Zope.Public</Permission>
>         </ZMI-Factory>

I don't like assuming that factory will always be classes.
In fact, they often won't be.

You also didn't specify a title for the factory.
 
>         <Protect>
>             <Permission>Zope.Public</Permission>
>             <Methods>query</Methods>
>         </Protect>
> 
>     </Content>
> 
>     <Content>
>         <Name>Job</Name>
>         <Class>JobBoardEx.Job.Job</Class>
> 
>         <Protect>
>             <Permission>Zope.Public</Permission>
>             <Methods>*</Methods>
>         </Protect>
> 
>         <View>
>             <Type>Browser</Type>
>             <Name>JobView</Name>
>             <Factory>JobBoardEx.JobView.JobView</Factory>
> 
>             <Protect>
>                 <Permission>Zope.Public</Permission>
>                 <Methods>index, simpleView, getSubmitter,
>                          getSummary, getDescription, getContact
>                 </Methods>
>             </Protect>
>         </View>
>     </Content>

Did you intend to register the view for the class?
This isn't possible now, and I don't think it's a good idea.

It would have been more helpful to have done a complete
example for step 5 or 6 of the tutorial.

...

Another comment is that namespaces are really needed to make the
system extensible in a sane way.

Jim

--
Jim Fulton           mailto:jim@zope.com       Python Powered!        
CTO                  (888) 344-4332            http://www.python.org  
Zope Corporation     http://www.zope.com       http://www.zope.org