[Python-Dev] PEP 246, redux
Phillip J. Eby
pje at telecommunity.com
Wed Jan 12 20:51:16 CET 2005
At 03:48 PM 1/12/05 +0100, Alex Martelli wrote:
>Demanding that the set of paths of minimal available length has exactly
>one element is strange, though, IF one is assuming that all adaptation
>paths are exactly equivalent except at most for secondary issues of
>performance (which are only adjudicated by the simplest heuristic: if
>those issues were NOT considered minor/secondary, then a more
>sophisticated scheme would be warranted, e.g. by letting the programmer
>associate a cost to each step, picking the lowest-cost path, AND letting
>the caller of adapt() also specify the maximal acceptable cost or at least
>obtain the cost associated with the chosen path).
There's a very simple reason. If one is using only non-noisy adapters,
there is absolutely no reason to ever define more than one adapter between
the *same* two points. If you do, then somebody is doing something
redundant, and there is a possibility for error. In practice, a package or
library that declares two interfaces should provide the adapter between
them, if a sensible one can exist. For two separate packages, ordinarily
one is the client and needs to adapt from one of its own implementations or
interfaces to a foreign interface, or vice versa, and in either case the
client should be the registrant for the adapters.
Bridging between two foreign packages is the only case in which there is an
actual possibility of having two packages attempt to bridge the exact same
interfaces or implementations, and this case is very rare, at least at
present. Given the extreme rarity of this legitimate situation where two
parties have independently created adapter paths of the same length and
number of adapters between two points, I considered it better to consider
the situation an error, because in the majority of these bridging cases,
the current author is the one who created at least one of the bridges, in
which case he now knows that he is creating a redundant adapter that he
need no longer maintain.
The very rarest of all scenarios would be that the developer is using two
different packages that both bridge the same items between two *other*
packages. This is the only scenario I can think of where would be a
duplication that the current developer could not easily control, and the
only one where PyProtocols' current policy would create a problem for the
developer, requiring them to explicitly work around the issue by declaring
an artificially "better" adapter path to resolve the ambiguity.
As far as I can tell, this scenario will remain entirely theoretical until
there are at least two packages out there with interfaces that need
bridging, and two more packages exist that do the bridging, that someone
might want to use at the same time. I think that this will take a while. :)
In the meantime, all other adapter ambiguities are suggestive of a possible
programming or design error, such as using interface inheritance to denote
what an interface requires instead of what it provides, incorrectly
claiming that something is a universal (interface-to-interface) adapter
when it is only suitable for certain concrete classes, etc.
>Personally, I disagree with having transitivity at all, unless perhaps it
>be restricted to adaptations specifically and explicitly stated to be
>"perfect and lossless"; PJE claims that ALL adaptations MUST, ALWAYS, be
>"perfect and lossless" -- essentially, it seems to me, he _has_ to claim
>that, to defend transitivity being applied automatically, relentlessly,
>NON-optionally, NON-selectively (but then the idea of giving an error when
>two or more shortest-paths have the same length becomes dubious).
No, it follows directly from the premise. If adapters are non-noisy, why
do you need more than one adapter chain of equal length between two
points? If you have such a condition, you have a redundancy at the least,
and more likely a programming error -- surely BOTH of those adapters are
not correct, unless you have that excruciatingly-rare case I mentioned above.
>BTW, Microsoft's COM's interfaces ONLY have the "inferior" kind of
>inheritance. You can say that interface ISub inherits from IBas: this
>means that ISub has all the same methods as IBas with the same signatures,
>plus it may have other methods; it does *NOT* mean that anything
>implementing ISub must also implement IBas, nor that a QueryInterface on
>an ISub asking for an IBas must succeed, or anything of that kind. In
>many years of COM practice I have NEVER found this issue to be a
>limitation -- it works just fine.
I'm actually open to at least considering dropping interface inheritance
transitivity, due to its actual problems in practice. Fewer than half of
the interfaces in PEAK do any inheritance, so having to explicitly declare
that one interface implies another isn't a big deal.
Such a practice might seem very strange to Java programers, however, since
it means that if you declare (in Python) a method to take IBas, it will not
accept an ISub, unless the object has explicitly declared that it supports
both. (Whereas in Java it suffices for the class to declare that it
supports ISub.)
More information about the Python-Dev
mailing list