The Skeptical Methodologist

Software, Rants and Management

Better Python: Abstract Factory in Python

Frequently design patterns are imported between languages with little thought to how a new language would better express them.  Witness Google’s C++ unit testing framework, which rather blindly follows JUnit even though Boost’s own unit testing framework, leveraging a few naughty macros and a lot of templating, reinvents unit testing in a more succinct and C++ way.  Or, along with testing, you can look at other’s Mock Object frameworks, mostly following the Java tradition versus Mock Objects using templates as proposed in this blog.

Another example would be the Abstract Factory, one of the more intimidating patterns, allowing you to write a GUI framework that somehow runs both on Windows and Macs (at least, that was in the brochure).  It provides a single point of interface to an entire collection of factories that produce new objects.  If you want a Windows Button, you ask the Windows factory.  If you are on a Mac, you get a Mac Button.  The point is, both of these Abstract Factories meet a required interface, and each of the functions on that interface return another abstract type a la the factory method pattern.  To put it in more modern parlance, it’s Dependency Injection, except on an insanely wide scale.

If we were trying to code Java in Python, we might come up with something like the following (forgive the spacing, I don’t really have the gumption to figure out the formatting right now…):

class GUI:

def MakeButton():

pass

def MakeWindow():

pass

class MacGUI(GUI):

def MakeButton():

return MacButton()

def MakeWindow():

return MacWindow()

And so on.  Then, to use the GUI abstract factory, we’d simply pass an instantiation of the factory itself to whoever needed to do GUI stuff.

def CreateChart(GUIType, *args, **kwargs):

GUIType.MakeButton()

GUIType.MakeWindow()

You get the point.  This is how you’d have to do things in a language like Java, however, in Python, we have a trick up our sleeve.  We already have a type that represents a class and function factory – it’s called a Module.  Modules can be passed around as first class types in Python, removing the need for the whole heavy Abstract Factory framework.  Simply pass the module you’d like your class to use in it’s constructor and boom, the ultimate in dependency injection.  This provides astonishing amounts of testability, decoupling and modifiability.

In one file, say Windows.py, we declare the following:

class Button(object):

#do button stuff

class Window(object):

#do window stuff

Then in another file, say Mac.py, we do almost the same thing – same names, except completely different implementation.  The minimal of repetition:

class Button(object):

#most of your changes occur here

At runtime, we detect whether we’re on a Windows or a Mac, and then inject this into whatever other classes we want to run!

def MakeChart(GUIType, *args, **kwargs):

x = GUIType.Button()

#somewhere else in code

import Windows

MakeChart(Windows, *args, **kwargs)

Basically, we’re taking advantage of the modules we’re already building to keep our programs separate, but explicitly telling our other functions and classes where to grab all their variable types.  It’s exactly the Abstract Factory pattern, but we leverage what we’ve already built instead of putting a whole framework on top of our modules to make them explicit.

I’m excited at the addition of Abstract Base Classes in Python 3.0.  Seeing the above example, I’d like to see the idea extended to making explicit interfaces on Modules themselves, fulfilling the ‘Abstract’ part of ‘Abstract Factory’.  Obviously, with Python’s duck typing today, this is not required.  But interfaces do more than simply catch interface bugs, they also communicate a lot of information to potential users.

Patterns usually are a sign that we’re missing something, that we want to express something that’s natural to solve a problem, but the language doesn’t support it.  Thankfully, many ‘patterns’ turn into idioms, or even better, simple one line expressions in high level languages like Python.  This is the reason these languages are so expressive.

Advertisements

January 30, 2009 - Posted by | Uncategorized

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: