[Zope3-dev] should the view lookup machinery call getAdapter?

R. David Murray bitz@bitdance.com
Mon, 1 Apr 2002 18:45:16 -0500 (EST)


On Mon, 1 Apr 2002, Casey Duncan wrote:
> R. David Murray wrote:
>  > One question:  how would the following hypothetical (but probably
>  > essential) adapter play into your scheme?
>  >
>  > <adapter
>  > 	factory="Zope.App.OFS.Memento.ObjectHubMementoBag."
>  > 	provides="Zope.App.OFS.Memento.IMementoBag."
>  > 	/>
>
> In that case the objects being managed would simply need to implement
> IObjectHubMementoStorable (which derives from IMementoStorable). This
> would, of course, need to be implemented somewhere 8^).

I think you missed my point <grin>.  The adapter above is the
*default* adapter used for an object that doesn't support *any*
relevant interface.  Ie: an arbitrary 3rd party component, or any
Z3 component whose author doesn't care where its memento data gets
stored, or didn't know he needed to specify it.  (This case borders
on magic, but I don't think it is, since the default directive
is right there in the zcml files).

> Another thought is that given how generic memento storage is, it would
> be cool to have more specific interfaces by function. That way you
> could, for example, use LDAP for security settings, and mementos for
> everything else (something you can't currently do, at least not easily).
> In that case I might define interfaces like:
>
> IMementoSecurityStorage
> IObjectHubSecurityStorage
> ILDAPSecurityStorage

And you are back to the MxN problem we started with, I think.

I thought this use case was what was happening in the security
machinery zcml declaration.  An object type that wanted to
store security stuff in LDAP would have an override directive that
used the ILDAPSecurityStorage interface instead of IMementoBag
(IMementoStorable in your scheme).

But the view is really the same, speaking to the same underlying
interface (IMementoBag).  So if you want to reuse the view, you
could adapt from ILDAPSecurityStorage to IMementoBag.  Which under
your scheme would mean the object would also have to implement
IMementoStorable, which would break the encapsulation of storing
just security settings in LDAP.

So it seems like to use interface inheritance to solve this,
you need to have a distinct interface tree for each component
that wants to store data on behalf of an object.  And there'd
be a default adapter going from (ex) IMementoBag to
ISecurityStorable...but who would do that getAdapter call,
and how would the view machinery know it was popssible?

Even if you can answer that last, I don't see a way to use interface
inheritance to avoid the MxN problem.  I think all we've done is
to move the MxN from zcml declarations into Interface definitions,
which seems worse!  (Remember, MxN is worst case in both situations;
in both situations the actual problem would be much smaller, though
MementoBag seems like it might come close to worse case).

I'm leaning back toward the idea that transitive adapters are
necessary, but additionally that the security machinery should be
look 'for' 'ISecurityBag', which would be a subclass of IMementoBag.
There'd be a default (passthrough) adapter from IMementoBag to
ISecurityBag, so that most objects would store security data in
memento bags.  But an object that wanted to store it in LDAP would
implement the ISecurityBag interface natively or through an adpater
that spoke to LDAP instead of one of the IxxxMenentoStorables.

I think that makes ISecurityBag a new kind of marker interface
(ie: an interface that extends another but adds no functionality
of its own).  And there should to be a way to optimize that
passthrough adapter into dissapearing when instantiated <grin>.

> Another thing that troubles me is that implementing IMementoStorable
> really gives carte blanc to anything wanting to stick mementos in an
> object. This would be alleviated with the finer grained interfaces
> above. To alleviate the bloating of interfaces being implemented by
> everything, you could still have a general IMementoStorable to tell Zope
> to store everything in mementos.

The whole idea behind MementoBag is to give carte blanc to anything
wanting to stick mementos in an object!  Which is why I say that
some default adapter like ObjectHubMementoBag (an adapter that
stores memento data without touching the object it is adapting) is
necessary.  But I agree, objects that want to store data on behalf
of other objects should implement this new kind of marker interface
so that target objects can have fine grained control if they need
it.

> OTOH, don't we really want an object to say: Just store my damn security
> settings for me. In which case you could have something like:
>
> __implements__ = ISecurityManageable
>
> Which means "Store security settings however you want to for me", the
> exact method being set in a zcml file. And you could also have
> IMementoSecurityManageable and ILDAPSecurityManageable et al, so that
> the class could be much more choosey if it pleased.

Better, I think, would be for there to be a default way for security
settings to get stored for objects that haven't bothered to declare
how they want them stored; sort of a stronger version of your "Just
store my damn security settings for me".  You could think of it as
the security system saying "just store this damn data for me", even
if the object isn't listening <grin>.

	<adapter
		factory="Zope.ComponentArchitecture.NullAdapter."
		provides="Zope.App.Security.ISecurityBag."
		for="Zope.App.OFS.Memento.IMementoBag." />

Like I said, I'm back to thinking transitive adapters are a better
solution to these issues.

--RDM