[TransWarp] Input wanted: addresses, adaptation, and attributes
Phillip J. Eby
pje at telecommunity.com
Wed Jun 11 14:08:33 EDT 2003
Currently, when you bind to an address such as 'pgsql:user:pw at server/db',
you get back a connection object of a "hard-wired" type. To change this,
you have to specify custom "object factories" in the retrieval context,
which requires fairly intimate knowledge of both what address is going to
be used, and how the underlying name retrieval mechanism works.
I'm thinking that it would be better (for some definition of better) to use
adaptation for this. For example:
myConn = binding.bindTo(
'pgsql:user:pw at server/db', adaptTo=storage.ISQLConnection
)
So, there's an explicit statement that you want the return value to be an
ISQLConnection. This is even more important when you are requesting a name
like 'theServer', or this is happening via a property lookup. Actually,
it's beginning to like a generally good idea to specify desired interfaces
on bindings of *any* kind.
Is there any strong objection to this? My thought is that if this becomes
the standard, then I can ditch the entire "object factories" system from
peak.naming. It's a convoluted mess that tries to keep the system as
flexible as JNDI, but the truth is that JNDI isn't really that
flexible. Sticking with the JNDI approach when we have something better
available doesn't make sense, since the JNDI approach is going to be harder
for me to document than adaptation. (Because I've already got
documentation for adaptation written!)
The refactoring would consist of removing all object-factory related code,
and that includes getting rid of 'retrieve()' methods from
addresses. Instead, we would define adaptations from address types to
specific interfaces. This would be a lot more flexible, as it would allow
an address' contents to be interpreted in more than one way.
A trade-off here is that when you have something that really does need to
be "retrieved", you'll now need to create an actual naming context. For
example, the 'import:' scheme that's in PEAK now should really always have
been a naming context, because there are actual objects to be retrieved by
importing. But for SQL URLs, there isn't anything to "retrieve". It's
just an address. The existence of 'retrieve()' has just made it easier to
duck the issue of whether something should have a naming context or not.
The distinction is rather subtle, and the current framework is pretty
ambiguous about it. For example, an LDAP URL can contain a specific path
to an entry, or a search query. The current system just gives you an LDAP
connection and leaves the rest up to you. It would make more sense if you
just got the LDAP address, and could adapt it to a connection, a query
result, or even a naming context (so you could browse the LDAP directory).
My thought at this point is that naming contexts should retrieve generic
objects according to what kind of context they are, and users then adapt to
specific objects. So, the 'import:' URL should have a context that loads
the named object (and then you can adapt it if needed). Pretty much all
other address types would stay as is, just being returned by the context
that looks them up. Instead of 'retrieve()' methods, there would be
adapters defined to appropriate interfaces. And you'd have to be explicit
about the interface you wanted, or you'd end up with an address instead.
Another bit of JNDI cruft that we have at present is the 'attrs' argument
that is in a lot of API and SPI interfaces. It's becoming more clear to me
that this is needless extra complexity in the presence of adaptation. If a
naming context has attribute information, that should be encapsulated in
some kind of "entry" object, not passed around as another argument. So I'd
like to get rid of it, especially since it's currently documented that the
only valid value for it is 'None'. This change would break existing naming
contexts. In particular, context._get() would be supposed to return just a
'state' instead of a '(state,attrs)' tuple.
The last bit I'd want to get rid of is "state factories". Instead of
naming contexts trying to use "state factories" to convert a storable
object, we'd now adapt to an interface. For example, a filesystem naming
context would try to adapt a storable object to an interface for writing to
files or directories, and when retrieving objects, it would return generic
file or directory objects that could be adapted back to
application-specific objects. (In other words, (de)serialization would be
a function of adaptation.)
Comments, anyone? Will this break too much? Does the requirement of
specifying an interface for a binding (or lookup) seem too strict? Any
other thoughts?
More information about the PEAK
mailing list