PEP 245

Alex Martelli aleaxit at yahoo.com
Thu Apr 5 06:03:52 EDT 2001


"Remco Gerlich" <scarblac at pino.selwerd.nl> wrote in message
news:slrn9co78i.70t.scarblac at pino.selwerd.nl...
    [snip]
> Common practice in Python is to do not even that, but just use the object
as
> given. If it doesn't have the methods then there will be an exception.
> Heavy unit testing is necessary anyway.

Sure.  But interfaces happen a lot BETWEEN units -- thus, they
yield less readily than one might hope for to the (excellent,
indispensable, splendid) practice of heavy unit-testing.

"Just go ahead and try to use it, possibly catch resulting
exceptions" is good in many cases, but it causes problems
when state is being modified by certain methods... and then
another method is missing, so the exception leaves state
in some in-between, inconsistent state.  "rolling back"
such partial, incomplete state alterations is generally not
an easy task.

Being able to ask the object about conformance to the
*whole* protocol you need BEFORE you start altering state
sure helps!  It's no complete solution, because the
object itself may be buggy -- it may BELIEVE it is
conformant to protocol XYZ, but be wrong about it --
but THAT is what unit-testing on the object should be
catching... that it IS correctly implementing those
protocols (contracts, interfaces, concepts) it says
it's implementing.


There is an unfortunately-large body of experience on
this problem, which is due to the frequent violation,
by the designers of COM interfaces, of the important
"interface segregation principle" (see, for example,
http://www.objectmentor.com/publications/isp.pdf).

When an interface is too fat, an object that purports
to 'implement' it may, in fact, often implement just a
_subset_; client-code attempts to call methods that
ARE in the interface, but that the object does not
fully implement, will raise some kind of exception.

An interface with 20 methods has over a million
possible subsets -- even considering each method as
only "entirely implemented" or "not implemented at
all".  It's not really sensible to expect client
code to cope with every subset, or even be tested
for all of them; checking may well not be feasible,
as it's often the case that there is no idempotent
way to verify that a method is in fact, not just
'present', but implemented in a way that can be
tried without undesired state-altering side effects.

Having +slim+, usable interfaces _and a way to
query for conformance to them (without, of course,
altering state if conformance is not present)_ is
a far better situation.  "One method at a time" is
just very rarely the optimal "granularity" (just
as having methods come in chunks of 20 or so is
quite rarely what one actually _wants_!).  This
can be worked around (as evidenced by the huge
amount of working COM client-code that manages to
more-or-less survive a world full of fat, partially
implemented interfaces:-), but it's a real waste of
programming effort to have to do it again and again
and again and...


Alex






More information about the Python-list mailing list