[Zope3-dev] interface conventions: default=_RAISE_ERROR

Gary Poster garyposter@earthlink.net
Sat, 11 May 2002 17:47:29 -0400


On Saturday 11 May 2002 04:04 pm, Martijn Faassen wrote:
> Gary Poster wrote:
> > On Friday 10 May 2002 08:26 pm, Guido van Rossum wrote:
>
> [special default to signal raising of exception]
>
> > > While we're at it, I don't particularly like the pattern.  If it is
> > > used I think there should be a *public* value so that a caller can be
> > > explicit about "I want the exception" rather than having to use a
> > > short argument list.
> > >
> > > Where this is used, would it be acceptable if the exception itself
> > > (KeyError?) was specified as the default value?  Or is an exception a
> > > valid regular default?
> >
> > Yup, better solution.  As far as I'm concerned, at least.  Can I start
> > using this, folks?
>
> What's the reason for the existence of the pattern in the first place,
> though? Why do you *want* to use it? I mean, Guido raised a legitimate
> issue there in my mind; having to handle exception raising defaults makes
> the contract of an interface harder to fulfill, and I don't see much
> of a benefit.
>
> _RAISE_KEYERROR right now only seems to be used in Containers and in
> the traversal interface. We were talking about changing the container
> interface to be more like a Python mapping, in that you can do
> __getitem__() access and the like. KeyError would then presumably
> be raised if an item cannot be found, and the default pattern is used
> with the get() method.
>
> You could argue the complexity of the latter interface (get and getitem) is
> the same as the former, but I disagree; in the former case you need a
> single method to behave differently (presumably with an 'if' or other
> conditional pattern somewhere inside), which is harder to forget while you
> implement the method (as it seems to work) and harder to deal with if you
> unthinkingly use the method. Plus it's also unlike Python where the default
> is None. In constrast, if you're going to implement get() on top of
> __getitem__ it's pretty hard to do it wrong.

This convention, or something similar, goes back at least to Zope 2 
development days, I think--long before my Zope interests.  In Zope 3, as you 
said, a _RAISE_ERROR-type marker is used in Containers; I didn't notice 
Traversal, but I believe it.  The idea is also throughout the 
ComponentArchitecture package, as I commented in my first email in this 
thread, although the interface signatures currently are misleading/wrong.  
They state default=None when the description and implementation actually 
follow the marker convention; I hoped to clarify this on the basis of the 
outcome of this thread.

I understand your argument, but I don't feel strongly enough about it to 
agree with you, and I think it is problematic for more complicated signatures 
like the ones in ComponentArchitecture.  If word comes down from on high that 
we should not use this convention, I'll be happy to adjust, but for now it 
seems to be fairly well-established in both old and current code, and I don't 
mind it.  I'm interested in polishing it, in the manner Guido suggested, but 
not eliminating it.

If you'd like to ponder and argue the issue a little more, I suggest looking 
at the interfaces in the ComponentArchitecture package as a conversation 
starter, remembering that every time you see "default=None" it's a lie: we're 
using a marker convention.  I've adjusted the interfaces in my sandbox to use 
the convention Guido suggested because I like it, but I have a number of 
other changes in here that are not ready for public consumption, so I'm not 
checking in.  In any case, look at IUtilityService, IViewService, 
IResourceService, IAdapterService, and IPlacefulComponentService and see if 
you see a better approach than using the marker convention for these.  

I think raising an error is "correct," returning a default is a useful 
shortcut, and combining the two on the basis of a marker is a reasonable 
compromise that's easy to code.  Duplicating the pertinent methods to 
parallel __getitem__ and get seems unnecessary and I don't care for it.  But 
again, I'm happy to accomodate a community or ZC decision.

Gary