[Zope3-dev] Re: Coarse-grained reuse.

Jeff Shell eucci.group at gmail.com
Wed Mar 15 18:38:55 EST 2006


On 3/15/06, Martijn Faassen <faassen at infrae.com> wrote:
> Jim Fulton wrote:
> > - We don't have a good way for installing collections of local
> > components that work together.  For our projects, we've used the
> > generation machinery to automate this, but that only works if you
> > want to install things in the root folder.
>
> Right. So far what we've done is some setup code to:
>
> * create utilities in the application's site object
>
> * create indexes in the catalog we just set up.
>
> * create some content objects that come with the application into the
> site object (typically folder-like things that will contain the actual
> content the user creates)
>
> Especially for the first two cases using custom Python code feels wrong.
> It'd be better if there was some framework this custom Python code could
> be registered with. I'm not thinking about the registration stack stuff,
> but at least some way to register "Hey, this code wants to install stuff
> into a site" somewhere, so that in my application I can use that. What
> it's doing is a bit like a factory, but it's different in that:

I think I understand what you're saying. I run this pattern a lot
myself. To date, I've used the event handler approach to catch when my
site is added. But also, to date, I've stuffed a lot of the setup code
into a single function called by the event handler.

I don't think there's anything wrong with "custom Python" code to set
this up. It's programmatic, isn't it? A lot of it may be repetitive,
and if that's the case, functions/methods can help. Are we all just so
used to writing big long blocks of code in Zope 2 Python Scripts that
we've forgotten we can do this?

I'm trying to abstract some common Bottlerocket patterns out into new
base framework/library for my company to use, and this is actually one
of them. I was trying to come up with something last night for just
this issue. Basically, I thought of writing a couple of interfaces
that would do something *like* zope.app.generations, but instead of
being a 'database opened' event response, used to automatically patch
persistent data with the expectations of code, these things would work
on a 'site added' event. What I didn't spend any time thinking about
was whether to have future upgrades go through this tool, or through
generations.

Anyways, I was thinking this would be done through adapters. For just
handling install, I was thinking of something like ISiteConfigurator.
Maybe a marker interface of ISiteConfigurable would be used for a
'site' to be registered with a built in event handler - although you
could write your own event handler and call the configurator yourself.

ISiteConfigurator would just have one method, 'configure'. In there,
you do what you want.

There would be a 'SiteConfiguratorBase' class offered (but not
required) that would provide helper methods like 'ensureUtility' -
things to take away the repetitiveness of the current registrations.
But it would be you (developer of the 'site') that would decide what
gets installed, and how. Sometimes, there are very common things that
have to be installed. But sometimes, it's very specific. IntIds is
very straightforward. A catalog requires setting up its indexes.
Setting up pluggable auth can require quite a bit of work, depending
on all of the pluggable auth bits you need. So it obviously can't all
be automated with a bunch of one liners.

The system, as I see it, is nothing grandiose. It's just something
that I hope will solve (for us) the problem of:

* Having and maintaining (and copying and pasting) the same event handler to
  every app.
* Having to remember some of the specifics of basic registration.

If we have a site that builds on another site, we could also subclass
from its adapter and provide any extended install features, or even
selectively ignore them. The wins are:

* Using an adapter to bind the configurator to the site allows the
  'framework' to handle when and how the configuration gets run for
  a particular site / added object, but doesn't worry about what it
  does.
* Use the wonders of object oriented technology to provide a base
  class with helpful methods for the common configuration chores.
* Use this same wonder to allow common sites to share common tasks
  for establishing local utilities.
* Still have the power to be as programmatic as needed, which can
  ensure that the utilities are established in a proper order and
  deal with specific situations regarding their establishment. Or
  just to handle dealing with very repetitive situations in an
  easier fashion.

Maybe something like that is what Jim's talking about in regards to assemblies?

ZCML really can't handle this. Not unless the ZCML in question was
basically a pointer to a callable object, at which point you've got an
event handler all over again. I'm looking at my code to set up the
authentication utility for some of our sites. Very specific rules
about what plugins are needed (users, groups, http credentials) and
things in those plugins (default groups). There's no way I'd want to
automate that in anything BUT Python. (Plus, in its current form, this
code can also be used by a view that responds to there being no auth
system setup).

--
Jeff Shell


More information about the Zope3-dev mailing list