Re: make zope.component.registry.Components inherit from dict?

Martin Aspeli <[email protected]>
Newsgroups gmane.comp.web.zope.devel
Message-ID <[email protected]>
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

_______________________________________________
Zope-Dev maillist  -  [email protected]
https://mail.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 https://mail.zope.org/mailman/listinfo/zope-announce
 https://mail.zope.org/mailman/listinfo/zope )
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.