[Python-3000] Adaptation: T->P vs P->P (original) (raw)

Tim Hochberg tim.hochberg at ieee.org
Mon Apr 3 18:14:03 CEST 2006


Nick Coghlan wrote: [SNIP]

Tim Hochberg wrote:

In this thread, Alex has been advocating adaption where types are adapted to protocols: T->P adaption for short. By contrast, my two sample implementations have involved Protocol->Protocol adaption where objects that implement a certain protocol are adapted to another protocol: P->P adaption for short. I suppose this also could be considered T->P->P adaptation since you look up the protocol from the type, but let's stick with the terminology P->P adaption.

Alex has been advocating for adaption for quite a while (I imagine it seems like forever to him), so I give his views here great weight. Still, something about T->P adaption has been bothering me, but until now I haven't been able to put my finger on it beyond a vague sense that pressing concrete types into service in this way is asking for trouble. Here's the problem I have with T->P adaption: it increases coupling between the various clients of the adaption process. Lets talk about these clients, I believe Alex said there were four: 1. The author of the type: T 2. The writer of the adapter: A 3. The person defining the destination protocol: P 3. The user of the whole shebang: U Now under a T->P regime, T needs to search out all relevant adapters and register them for their type. Similarly when adding a new adapter, A needs to search out all relevant classes and register the new adapter for them. Thus A and T become highly coupled. This misses the whole point of dynamic adaptation.

You dropped this bit of context:

[I realize that I've artificially constrained who registers what, but the fact remains that someone has to do the registrations at some point. ...]

T and P might define a few convenience adaptations (e.g. to or from standard library interfaces), but A and U will usually be the same person.

I was simply attempting to copy Alex here. I more or less agree with you. Or more precisely, I agree that A will be a U. There may be other users that come after that also use A's work. But I'm muddying up the jargon here, so I'll stop.

Suppose framework X produces a Wibble,

and framework Y expects an IWobble in various places. The integrator (U) needs to plug them together. If Wibble provides the right interface, U can simply write:

IWobble.registertype(Wibble) Or, more commonly, U may need to write an adapter: class WibbleAsIWobble(object): def init(self, thewibble): self.thewibble = thewibble # delegate the IWobble API to the Wibble instance IWobble.registertypeadapter(Wibble, WibbleAsIWobble) Either way, after either conformance or the adapter have been registered, a Wibble can be used seamlessly anywhere an IWobble was expected.

Suppose instead that the interface of framework X claims that it produces a sequence, or a file-like-object or even a WibbleLike object. Then U/A needs to dig into the guts of framework X to determine what concrete types it actually produces in order to register them for their adapter. Then, when A/U downloads the new spiffy version of framework X that now can also produce the new WibbleLike object SuperSpiffyWibble, things break until A/U figures out what new types can be produced and updates things accordingly.

You can work around this if all the WibbleLike objects in framework X inherit from some base class WibbleBase (assuming that you are walking the MRO), but tying protocols to classes like that is not really the python way. And could be a pain in the neck, particularly if some of the types involved are implemented in C.

With P->P addaption, the situation is better. The author of framework X can simply document that it returns something that satisfies the WibbleLike protocol. Then the most that A/U ever needs to do, regardless of how many differently implemented Wibbles the frameworks spits out is:

 adaption.register_adapter(WibbleLike, WobbleLike, WibbleAsWobble)

Pep 246 and PyProtocols don't seem to implement either P->P or T->P adaption. That's because the conform method can do pretty much anything it wants -- the other portions of PEP 246 appear to be pretty much vanilla T->P. In a sense, P->P adaption is an attempt to come closer to the power of PEP 246 without the complexity of the arcane identity/conform/adapt/registry dance.

Zope adapation appears to be P->P, although it can also do T->P. In general, it should be trivial to have a P->P setup also do T->P adaption.

Regards,

-tim



More information about the Python-3000 mailing list