[Zope-dev] make zope.component.registry.Components inherit from dict?
Martin Aspeli
optilude+lists at gmail.com
Tue Nov 24 00:54:26 EST 2009
Hi Chris,
Chris McDonough wrote:
> Martin Aspeli wrote:
>> We need to make sure that we're not inventing a different way to achieve
>> something which is already possible. This will lead to confusion,
>> because people will have to know "which way" is applicable in a given
>> situation, and the distinction will seem arbitrary.
>
> I fear we are indeed inventing a different way to achieve something which is
> already possible. We aren't doing it arbitrarily, though: the current way just
> requires the use of an interface instead of a string. Interface usage for such
> a simple pattern implies a cognitive load that appears to exceed the pain point
> of most Python developers who are not already familiar with Zope. So we'd like
> to ameliorate that as best we can.
I wish I knew what "ameliorate" meant, but I'm sure I agree.
My concern is that we also have a pretty large existing user base to
worry about, and we wouldn't want to confuse them. Or, indeed, new users
confronted with code that has been written up to this point.
> >> In a system like this, there are no interfaces; the string 'root_factory'
>>> performs the same job as the IRootFactory interface for registration and
>>> lookup. I'd like to make the ZCA registry operate like this. There's really
>>> no reason for there to be an interface hanging around to represent this thing:
>>> we're using the ZCA as a complicated dictionary here.
>> I think there is a reason, though you may not agree it's a good one. The
>> interface makes a promise about what the component is supposed to be
>> able to do. We don't enforce that in our duck-typing programming
>> language, but I think there is value in being able to say, "I want an
>> object that conforms to this interface (i.e. delivers what the interface
>> promises) - please get me the best one you've got".
>
> That is indeed the promise. But obviously the object you get back needn't
> *actually* implement the interface you asked for; it's only conventional. It
> is the same with a dictionary lookup: if you document that, for your
> application, reg['root_factory'] will return an object implementing
> IRootFactory, it's pretty much equivalent as far as I can tell. Use of the ZCA
> API to store and retrieve instances implementing an interface isn't required to
> get benefit out of the existence of that interface.
No, that's true, except perhaps that it's two things to worry about: an
interface and the related name.
> I guess I can only point at the rationales in
> <http://docs.repoze.org/bfg/1.1/designdefense.html#bfg-uses-the-zope-component-architecture-zca>
Yep, and I agree with these.
>> Off the top of my head, another way to think of this *might* be to say
>> that the 'dict access' is basically looking up a *named* utility
>> providing a very generic marker interface, e.g.
>> zope.component.interfaces.IUtility or even just
>> zope.interface.Interface. That way reg['foo'] == getUtility(IUtility,
>> name='foo'). Obviously, assignment would register in the same way.
>>
>> I'm not sure it's "better", though. :)
>
> That would also be fine, and it would normalize things a bit, although the
> implementation would be harder and it would result in slower lookups. But if
> it made folks feel better than inheriting from dict, I'd be +1 on it.
I think it would be nicer, because we could tell a story like this:
- if you just want a place to store things by name...
- ... which can be overridden at runtime or customised with local
components ...
- ... and you don't care too much about the notion of an interface ...
- ... then here's the ZCA way to look up a component by name only
To register:
reg = getSiteManager()
reg['rootfactory'] = MyRoot()
To retrieve:
reg['rootfactory']
To delete:
del reg['rootfactory']
The equivalent ideas would be:
reg.registerUtility(MyRoot(), provides=Interface, name='rootfactory')
getUtility(Interface, name='rootfactory')
reg.unregisterUtility(provides=Interface, name='rootfactory')
Although I suspect we want a marker interface that's a bit more specific
than just 'Interface' since we already have some things that register
interfaces as utility, I think. So maybe:
class IAnonymousUtility(Interface):
pass
Martin
--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book
More information about the Zope-Dev
mailing list