When OO attacks Python
In response to “Python for Humans”,
I blame GOF for making Python Standard Libs hard. The patterns described were for an OO system where functions were not first class. Python didn’t need to be complicated.
If you have a look at the older libraries, most of them were written in a procedural style. Not only that, it is very amenable to testing in the REPL.
import smtplib
s=smtplib.SMTP("localhost")
s.sendmail("me@my.org",tolist,msg)
note the absence of doers like “Adapters”, “Handler”, “Manager”, “Factory”
If you have a look at the XML library, roughly when “patterns” became popular, this style of thinking infested standard library contributions. It also coincides with a time when camelCased function names crept into the python standard library.
Here’s one in xml/dom/pulldom.py:
self.documentFactory = documentFactory
Once you see this, you know you are in for some subclassing. You can no longer REPL your way to figure out how things work, and you now have to consult the manual.
Here’s more pain from libraries of the same era, some of these I’d argue un-Pythonic:
#xml/sax/xmlreader.py:
def setContentHandler(self, handler):
#wsgiref/simple_server.py:
class ServerHandler(SimpleHandler):
#urllib2.py:
class HTTPDigestAuthHandler(BaseHandler,
AbstractDigestAuthHandler):
The last example is especially jarring. Abstract classes have a place in strongly typed world to declare interfaces, and help with vtable-style dispatch. In Python, where you have duck-typing and monkey patching, a class that virtually “does nothing” on its own stands out like a guy in a tux at a beach party.
Even logging is infected by the same over-patterning. logging/__init__.py:
class StreamHandler(Handler)
LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
“Managers” – what a pain when plain function handles would have done the job. Does this name even tell you what task the class performs?
#multiprocessing/managers.py:
class BaseManager(object)
If anyone remembers, Java had to do OO in a big-style with OO everywhere — there were no alternatives.
Initially, buttons had to be subclassed just to handle click events, since functions were not first class objects. Then someone came up with a MouseListener interface, which proved too unwieldy to handle a single click. So the MouseEventAdapters came into being.
Therefore, to handle a click in a “pattern” manner involves
- an anonymous class
-
- which subclasses MouseAdapter
-
- which subclasses MouseAdapter
-
- which implements MouseListener,
-
- which subclasses MouseAdapter
-
- which overrides MouseClick.
Publishing how industry solves this problem of “MouseClick” over and over as a pattern [design pattern is a general reusable solution to a commonly occurring problem within a given context in software design] only gives legitimacy to an approach that has dubious wider applicability.
Heavens help the future developers who are forced to do it because it is now recognized as being industrially “good practice” and codified in a reknowned book.
It isn’t!
It was a style that was forced by the constraints of a language.
This is neither pythonic nor necessary:
panel.addMouseListener
(
new MouseAdapter ()
{
public void mouseEntered (MouseEvent e) {
System.out.println (e.toString ());
}
}
);
Embracing “foolish, unschooled” thinking, this would be rendered in Python as:
def mouseEntered(event):
print event
panel.mouseEntered = mouseEntered
or for multiple event handlers
panel.mouseEntered.append(mouseEntered)
This style of API again allows effective exploration on the REPL.
About this entry
You’re currently reading “ When OO attacks Python ,” an entry on Chui's Counterpoint
- Published:
- 1.4.12 / 8am
- Category:
- Python
Comments are closed
Comments are currently closed on this entry.