idioms for abstract base classes

zooko at zooko.com zooko at zooko.com
Tue Apr 24 16:18:56 EDT 2001


 Robin Becker <robin at jessikat.fsnet.co.uk> wrote:
>
> what's the best way to spell an abstract base class so that
> 0) base is B and A inherits from B
> 
> 1) doing B() causes an exception


You can see here[1, 2, 3] how I did this in Mojo Nation[4].  I made a
pure-abstract base class (i.e. an "Interface") named "CommsHandler", a
non-abstract base class named "BaseCommsHandler", and various subclasses named
"{TCP,Crypto,Dummy}CommsHandler".

It was a complete failure.  Oh, not the "raising an exception if someone invokes
a non-implemented method" part.  I just put it assertions, as you can see in the
CommsHandler class, and never had to touch it again.  (Indeed, nobody *ever*
accidentally invoked a non-implemented method as far as I can remember.)  The
failure was the whole idea of having base classes.


It turned out that there was no functionality that was actually common to both
CryptoCommsHandler and TCPCommsHandler except for some features (namely, the
ability to chain together an arbitrarily deep "stack" of comms handlers) which
we never actually needed.

It turned out that in addition to wasting my time implementing a feature that we
never needed, I also made the resulting code hard for my fellow hackers to
follow.  Due to the polymorphism and due to the common "parallel inheritance
hierarchy" problem, it was very difficult even for *me* to understand how
control flowed through the classes, which became a serious problem when I came
back to them six months later in order to evolve and debug them.


Eventually, we started just undoing the inheritance -- I changed
CryptoCommsHandler to just implement all of its methods instead of using any of
the ones inherited from BaseCommsHandler, and next time I touch TCPCommsHandler
I'll do the same to it.  Then we can nuke DummyCommsHandler (which is only good
for testing the unused "chaining" feature anyway) and CommsHandler and
BaseCommsHandler.  It will feel really good to get rid of those after all the
trouble they've caused.


I think a wise old monk once said "Choose the right tool for the job, and then
use the tool in the way it was designed to be used.".

Python has dynamic structural typing, which gives rise to rapid prototyping,
flexible code re-use, and minimal hindrance to the programmer, as well as to
clear designs and readable code.  USE the dynamic structural typing, and do not
attempt to regress to C++/Java style static/dynamic named types, like I did.


(If you *really* want static, name-based typing, then switch to C++, Java,
Eiffel, Ada95 or something for the modules that need that kind of style.)


In fact, I suspect that premature design, such as the mistake described here, is
the most common error in software engineering (this contradicts the common
belief that insufficiently farsighted design is the most common problem in
software engineering).  Perhaps part of this is the language used.  In assembly
or C, it is harder to see what your design currently *is* and it is harder to
refactor your design, so it is easier to get stuck with code that has outlived
any design and has become a mere hairball.  But in Python it is easy enough to
see and to change your design that the best approach is usually to do "just in
time design".  (C++ and Java fall into an ugly "worst of both worlds" camp where
both too-early and too-late design can bite you.)


Please see Kent Beck[5]'s book _Extreme_Programming_Explained[6], which is
delightfully readable and thought-provoking.  Do not be put off by the title.
I personally ignored the "Extreme Programming" meme for at least a year, because
I simply didn't want to know about anything so silly and hyped-up as "Extreme"
anything.  This was a mistake -- actually it is a very sensible and rational
practice of programming that any experienced Python hacker will find both
familiar and refreshing.


Regards,

Zooko

[1] http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/~checkout~/mojonation/evil/common/CommsHandler.py?content-type=text/plain
[2] http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/~checkout~/mojonation/evil/common/CryptoCommsHandler.py?content-type=text/plain
[3] http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/~checkout~/mojonation/evil/common/TCPCommsHandler.py?content-type=text/plain
[4] http://mojonation.net/
[5] http://c2.com/ppr/about/author/kent.html
[6] http://www.amazon.com/exec/obidos/ASIN/0201616416/103-8730908-0760613





More information about the Python-list mailing list