[Interface-dev] Re: Interface and Adapter Demo
Christian Robottom Reis
kiko at async.com.br
Sun Jun 27 14:48:03 EDT 2004
On Sun, Jun 27, 2004 at 09:12:55AM -0400, Stephan Richter wrote:
> Hi Christian,
Hey Stephan, this was great. I've made some comments below, from the
viewpoint of a complete newbie to z.i:
> I have finished the example we started last night and commented it. Since I
> thought that other people might find this non-Zope-specific example helpful,
> I CCed the Zope 3 Dev and Interface Dev mailing lists.
Maybe this could be added to zope.interfaces as a HUMANS.txt document <wink>.
> For statistical reasons we often want to know the size of a file. However, it
> would be clumsy to implement the size directly in the file object, since the
> size really represents meta-data. Thus we create another interface that
> provides the size of something.
Just an orthogonal thought: is it really *that* clumsy to implement the
size as part of the file object? Or it is more of a design decision that
for certain situations makes sense and for others not?
> >>> class ISize(zope.interface.Interface):
> ...
> ... def getSize():
> ... 'Return the size of an object.'
> ...
>
> Now we need to implement the file. It is very important that the object states
maybe s/very important/essential/
This was one thing that I didn't take into account initially -- the
registry is designed to work exclusively with Interfaces.
> Next we implement an adapter that can provide the 'ISize' interface given any
> object providing 'IFile'. By convention we use '__used_for__' to specify the
> interface that we expect the adapted object to provide, in our case
> 'IFile'. However, this attribute is not used for anything.
Is the convention to use a tuple if used for more than one Interface, or
would that be a `bad thing'?
> Again by convention, the constructor of an adapter takes one argument, the
> context. The context is an instance of 'File'
perhaps ... in this case is an instance ...
> to extract the size from. Also by convention the context is stored in an
> attribute 'context' on the adapter. The twisted community refers to the
attribute named 'context' perhaps.
Does it make sense to have adapter-specific names, such as naming the
attribute `file' in this case, given the improved understandability of
the adapter's code, or is the adapter's code usual too short for it to
matter?
> Now that we have written our adapter, we have to register it with the adapter
> registry, so that it can be looked up when needed.
>
> >>> from zope.interface.adapter import AdapterRegistry
> >>> registry = AdapterRegistry()
s/the adapter registry/an adapter registry/
perhaps, and indicate that we're using a single one here, and that it
needs to be explicitly instantiated?
> Register an adapter that adapts from 'IFile' to 'ISize'. The first argument to
> the registry's 'register()' is a list of original interfaces. In our cause we
s/is a list/method is a list/ perhaps
> have only one original interface.
I find this section a bit heavy on required concepts. You might want
to use something from this alternative summary:
The registry keeps a map of what adapters implement an interface on
behalf of other interfaces. To register FileSize, an adapter that
adapts IFile-providing instances to the ISize interface, we use the
register() method::
>>> registry.register([IFile], ISize, '', FileSize)
The first argument is a list of original interfaces; in our case,
FileSize only adapts instances providing one interface, IFile.
Using a list makes sense when the same adapter is available for
multiple interfaces -- in our case, it might make sense to adapt
other `sizeable' objects, such as IString and even IDistance.
The second argument is the interface the adapter provides, in our
case 'ISize'.
[...]
> The third argument in the name of the adapter. Since we do not care
> about names, we simply leave it as an empty string.
Conventionally (perhaps Zope-conventionally <wink>), what are these
names useful for?
> us to get an adapter instance by simply calling 'ISize(file)'. To make use of
> this functionality, we have to register our registry with some hook mechanism.
Magical, magical adapter_hooks. It took me a while to realize that there
was something else I needed to do to get interfaces to use the registry
to determine how to adapt a certain instance. In hindsight, that makes
sense: you might have multiple registries, registries used in certain
situations and others in others, but it's completely non-obvious at
first sight.
.. we need to add our registry to the adapter_hooks list, which is a
member of the adapters module. This list stores a collection of
callables that are automatically invoked when IFoo(obj) is called;
their purpose is to locate adapters that implement an interface for
a certain context instance.
perhaps.
If we *must* write our own adapter hooks, then it should say so
somewhere; since here is as good a place as any, I suggest:
You are required to implement your own adapter hook; this example
covers one of the simplest hooks that use the registry, but you
could implement one that used an adapter cache or persistent
adapters, for instance.
> >>> size = ISize(file)
> >>> size.getSize()
> 7
>
> That's it. I have intentionally left out a discussion of named adapters and
> multi-adapters, since this text is intended as a practical and simple
> introduction to Zope 3 interfaces and adapters. You might want to read the
> 'adapter.txt' in the 'zope.interface' package for a more formal, referencial
> and complete treatment of the package.
Note that adapter.txt makes my brain feel soft (and someone else has
said the same thing to me -- though perhaps just to make me feel
better). It seems to be at points trying (and succeeding <wink>) *on
purpose* to confuse me, via the use of integers (what is 12?) in place
of "context". This is actually compounded by the adapt_0_to_42 adapter
hook exemplified in interface.py -- I was almost sure adapter_hooks were
what I wanted but the example just didn't make sense -- it doesn't even
use the iface argument, and nowhere does it suggest I might want to use
the registry.
It would help tons just to add the simplest adapter hook that used the
registry as an example, and point to it -- many people will need
something more specific, but there's at least something to start from.
Thanks a lot for taking the time to write this.
Take care,
--
Christian Robottom Reis | http://async.com.br/~kiko/ | [+55 16] 3361 2331
More information about the Interface-dev
mailing list