[TransWarp] The return of naming.Reference()
Phillip J. Eby
pje at telecommunity.com
Tue Jul 15 12:55:36 EDT 2003
During the 0.5 alpha 3 release cycle, I changed peak.naming to require that
you use adaptTo to convert addresses to desired objects. The intent was to
get retrieval logic out of address classes, in order to reduce the
unnecessarily tight coupling between addresses and things retrieved, and to
get rid of the IObjectFactory interface and utilities.
So far, this has not worked very well. I think that the double amputation
was a success, but the patient would now like his healthy leg back. ;)
The original idea of making addresses "object factories" was that it
eliminated the need to create custom Context subclasses to go with every
new kind of address. JNDI dealt with this issue somewhat differently:
naming contexts generally store 'Reference' objects, which specify a class,
factory, and zero or more addresses. The addresses are either strings or
binary data, and are not interpreted. Thus, the class and/or factory
specified in the reference were responsible for interpreting the addresses.
I thought this was rather silly, since for 'peak.naming', this just pushed
right back to the issue of how to resolve an address in the first
place. Early versions of the naming package wrapped addresses in a
Reference() object, then unwrapped it again later in order to .retrieve()
it. So, that code got factored out a long time ago, as it seemed to make
no sense.
Recently, we've gotten some experience in actually using peak.naming with
our "enterprise" naming systems, and have come to realize that having
References() does make sense, for somewhat different reasons. For one
thing, there are many objects one may wish to store in a naming system,
that really don't make any sense as URLs. But, we don't always have the
option of storing a pickle or something of that sort. Plus, pickling is
tightly tied to a specific module structure, but directory contents may be
used by multiple deployed application versions. So, we'd like some
indirection ability.
Here's what I propose to do. I will re-introduce naming.Reference, and
naming.IObjectFactory. However, IObjectFactory will not be used as a
utility any more, nor will addresses implement it. Instead,
naming.Reference and naming.LinkRef will implement it, as will any objects
that want to be creatable *from* a Reference (e.g. database connections,
lockfiles, logfiles, etc.) Naming contexts will attempt to adapt retrieved
objects to IObjectFactory before returning them to the caller, and the
AddressContext base class will once again wrap addresses in a Reference
before returning them.
Reference objects will have a "class/factory name", and a sequence of
"addresses". The "class/factory name" will actually be looked up in a
property namespace ('peak.naming.factories'), where the default will be to
interpret the factory name as an import string. Thus, one can use import
names as class/factory names, but you will be able to "redirect" them using
configuration properties, if needed. References will be able to find the
specified factory and invoke it, passing in the reference's data along with
any available context information (e.g. the context the reference was found
in).
Here is the likely impact on existing PEAK and user code using peak.naming:
* The adaptTo=IWhatever requirement will go away again, although code using
it will not break. It will simply be optional for most naming system
usage. (Of course, it's still suggested that you use it for early
detection that you've retrieved something you can't use!)
* The current adapter declarations from address classes to "desired object"
interfaces will be replaced with a method that goes on the "desired object"
class directly. This method will need to accept a Reference and some other
parameters (TBD), and return a new instance. For example, SQLConnection
will grow such a secondary constructor method.
* Addresses will have a new attribute, 'defaultFactory', that will be used
by AddressContext to create a Reference() from an address. This should be
the qualified name (dotted import path) of the "desired object" class.
Notice that this means that naming contexts which can store References will
be able to either use the default interpretation of an address, or store a
Reference to a different class, bound to the same address. (For example,
one could create a reference to either a PsycoPG or PygreSQL connection,
using the same 'pgsql:' address.)
Comments welcome, preferably *before* I implement this... ;)
More information about the PEAK
mailing list