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
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4