[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