[Zope-dev] implementing zope.component 4.0

Martijn Faassen faassen at startifact.com
Mon Nov 30 11:47:27 EST 2009


Hey,

Gary Poster wrote:
> On Nov 27, 2009, at 6:32 AM, Martijn Faassen wrote:
[snip]
>> So now that we've had some discussion and to exit the "bikeshed"
>> phase,
> 
> Wow.  That's abrupt, for something at the root of the entire stack.

I realize now that exiting the bikeshed phase was premature. Then again,
we don't want to go into circles about APIs forever. Recent discussions
were focused on backwards compatibility, so that's progress.

[snip]
> I am in favor of the above, given a backwards compatibility story
> that makes existing packages work.

Yay!

>> Utility lookup:
>> 
>> IFoo()
>> 
>> Named utility lookup:
>> 
>> IFoo(name="foo")
>> 
>> Utility lookup with a default:
>> 
>> IFoo(default=bar)
> 
> I disagree with this.  More below.

[snip]
> As a matter of mechanics, when you register something we call an
> adapter, it is a callable that takes one or more arguments.  If we
> were going to follow the pattern that Marius laid out to establish
> what happens when, then we have this, roughly:
> 
> register callable that takes two arguments: IFoo(bar, baz)
> 
> register callable that takes one argument: IFoo(bar)
> 
> register callable that takes no arguments: IFoo()
> 
> If instead we have the last step as what is proposed here
> 
> register non-callable IFoo()
> 
> then I think that breaks an important pattern for usage
> understandability.

I still don't see why that isn't an implementation detail. How we get an 
IFoo doesn't concern us when we're calling it, as long as we get an 
IFoo? Even with adaptation a singleton could be returned; it's just the 
implementation of such would be different.

If we take Marius' pattern, registring a singleton directly would simply 
be a shortcut API for registring a factory for utilities. (Utility 
factories would make it easier to implement local utilities that aren't 
ZODB-backed...)

> That is, IFoo() can have a semantic if that is valuable, but it is
> not the same as registering and getting non-called singletons.

What is this valuable semantic?

[snip]
> (To be complete, I am in favor of ditching "subscription adapters" in
> favor of other mechanisms related to named singleton lookups.)

I really need to think through subscription adapters; I haven't done any 
analysis about those.

> 2) The term "utility" is another barrier to understandability.  They
> are singletons.  Explaining them as such is a "well, why didn't you
> say so" experience.

Another way to explain utilities is that getting a utility is a lot like 
importing something in Python, except that what is imported is pluggable 
and the required interface is specified explicitly.

> Therefore, I am in favor of removing the necessity to use the word
> utility.  That said, they are not factories.  They should not be
> mixed with the two.  My preference for future changes is to have an
> API using the ``singleton`` name.  

"import by interface" to me sounds like it'd clarify matters for more 
Python programmers. Singleton has all kinds of design pattern 
connotations that don't really apply here.

> Moreover, I think that some of the
> use cases that Marius referred to for underpowered "utilities" coud
> be remedied by having a utility/singleton lookup that allowed looking
> up by required values like the adapter/factory lookup.

I don't understand. Could you rephrase?

>> Features off the table for now -------------------------------
>> 
>> Saying an interface is implemented by a class (Python 2.6 and up)
>> with a decorator we'll leave out of the discussion for now.
>> 
>> It would also be come up with an improved API to look up the
>> adapter *before* it is called, but I'd also like to take this off
>> the table for this discussion.
> 
> It seems to me that this, along with the documentation call that
> Chris gave, is a much more valuable immediate effort.  One of the
> biggest complaints I heard was with debugging.  I've spent some
> thought on the debugging story, and have some APIs sketched out in my
> experiments--it was one of the first things I worked on.  To do it
> cleanly (the way I envision) would require some work, but a first cut
> wouldn't be too bad.

Hm, I disagree about what's more valuable. I'd be quite happy when I can 
grab utilities and multi adapters without having to refer to 
zope.component all the time. Being able to look up an adapter without 
calling it in a convenient manner, not so.

But multiple efforts can certainly take place in parallel, if we have to 
volunteers.

[snip]
> I share Baiju's dislike of inventing __*__ names.  What is the
> necessity?  At least __future__ has precedence, I suppose, but Python
> devs have expressed their opinion clearly now that __*__ is theirs,
> and I think we should respect it in upcoming decisions.

Ah, I vaguely recalled something about __*__ being theirs now, but 
wasn't sure.

> Finally, per Martin's points, I'm not sure zope.component can
> actually ever deprecate the old spelling, so I'm not sure __future__
> has the right semantic.  This is really __alt__ or something, IMO.

I think it can deprecate the old spelling and eventually eliminate it, 
but it'll take quite a while.

It's the deprecation pattern we've used before:

* give warnings when someone use it in the deprecated way.

* eventually don't allow the deprecated way anymore.

> Alternatively, there's Shane's suggestion of a convenience wrapper.
> I was thinking about that approach too.  It has obvious usability
> disadvantages over having the preferred API immediately available.

Yeah, having to invoke the wrapper would be quite a drawback.

[snip]
> *Any* kind of backwards incompatibility is a huge deal.  I don't find
> that the simple improvements described here merit any kind of
> backwards incompatibility.  IMO, there needs to be a more compelling
> argument for that.

Yes, backwards compatibility as I said above is my favorite discussion. 
That's why I keep bringing it up. I just wanted to frame the debate in 
such a way so as to consider APIs separately from backwards 
compatibility and then see how we can get from A to B.

> (To be clear, I'm not sure my experiments will turn up changes that
> merit backwards incompatibility!)
> 
> The zope.component API is done, I think.  We can experiment with
> other tools that provide a support shim for it, but breaking it is
> pretty questionable.

I think having a multi-year deprecation path to do a change is at least 
a possibility. But it shouldn't be undertaken lightly.

[snip]
>> Most importantly, any volunteers?
> 
> While I like your desire to move forward, in this particular case I
> think this speed is rash.  I'd also prefer work on debugging tools
> before these syntax changes, but that's the kind of thing driven by
> who wants to do the work.

I think there are multiple kinds of speed:

a) the speed by which discussions lead to conclusions and a plan of action.

b) the speed of implementing the result of the discussion.

c) the speed by which any changes will be introduced to users.

With step c we should be very careful.

With step a, if you don't push towards conclusions and a plan of action, 
this step is never completed. The debate just fizzles out. So that's why 
I propose conclusions to see whether we can continue, and to limit the 
scope of discussions. If people don't like the conclusions they make it 
loud and clear. :)

With step b, if you slow that down too much (by never concluding step a, 
for instance), you lose all energy and things never happen at all.

Regards,

Martijn



More information about the Zope-Dev mailing list