Sometimes you just gotta monkeypatch…

Recently Guido offered up a couple of interesting recipes for cleaner monkey_patch implementations via decorators and metaclasses.

I think monkeypatching can be a very useful tool in the same way that a jackhammer or a shotgun can be useful tools. When you need them, nothing else can do the job as well. Of course, you can always smash the cement by hand with heavy iron rods — as is sometimes done in India, where labor is often cheaper than tools… Feel free to make your own analogy to using static languages and the trend towards code generation, rather than having the right tool for the job. But don’t expect me to do it, I’m trying to take the high road today ;)

Anyway, some of the responses have been along the lines of “I like my monkeypatching to look ugly, because it deters people from doing it.” And while I have a lot of respect for some of the folks saying this, I’ve never been a fan of this kind of “syntactic vinegar” argument. It seems to me that it’s better to make complex things seem easy than it is to make simple things seem hard. And it’s kind of paternalistic, and not consistent with the “we’re all consenting adults here” philosophy behind Python. Sure people could do stupid things with these tools, but I think it’s a bad idea to spend your time trying to stop hypothetical bad programmers from doing stupid things.

In other words, we shouldn’t make jackhammers more ugly and complicated just because you would smash your living room wall to pieces if you tried to hang a picture with one. ;)

And I think these patterns are useful. The first decorator syntax is particularly valuable for stubbing interface points out for testing purposes. Hey, a it’s a “mock framework” in 5 lines of code. The second looks like a nice thing to have around for testing purposes too. I’m sure there are uses beyond testing, but I know that’s where I’m likely to start applying these monkeypatching helpers.

5 Responses to “Sometimes you just gotta monkeypatch…”

  1. Meh. Just stick a docstring or comment on it saying, “Please replace this”, and all of a sudden you’re doing sexy Dependency Injection and Inversion of Control instead of evil monkeypatching.

  2. Yea, in other languages they call monkeypatching open classes, or label the things we can do with monkey patching “inversion of control” and generally think that these meta-programming kinds of things are cool.

    And they are. They are useful tools. Python has a bit of nasty monkey-in-the-mouth taste from bad monkeypatching experiences which were hard to understand and debug. And there is some truth to that. Metaprogramming in general can make debugging more interesting.

    If we still built housed out of straw and mud, home repairs would be super cheep and easy too. But, me I’m still gonna use my low flow toilets, insulated walls, electric wiring, and polyvinyl siding, even though those things are more difficult to debug and more expensive to replace.

    My point, is that in software, as everywhere else, it’s all about trade-offs.

  3. Monkey Patch was meant to be a “less forceful” sounding term than Guerilla Patch (misheard as Gorilla Patch). Guerilla patches are modifications made to your framework or library code without your knowledge by another add-on product. The metaphor being you install someone’s add-on product to your application and that add-on has changed some framework behaviour to make their code work. This breaks your own code – hence the modifications to the behaviour that you were relying on has been changed against your knowledge – guerilla warfare in code.

    Considering that this term originated from Zope, which embraced magic such as acquisition, casual monkey patching is considered harmful, while other forms of metaprogramming and dynamic trickery were not (at least back in the 90′s and early 2000′s, Zope has mostly moved to an explicit is better than implicit attitude). Monkey patches are a good way of expressing, “we should change this framework code, try it out in your sandboxes before we include it in trunk and see if it causes any problems.”

    Plone’s Archetypes for example generates methods dynamically based on a schema declaration, but this is never referred to as monkey patching.

    Inversion of Control is something that is common to almost all frameworks, it sounds rather fancy but it just means that some portion of the control flow of your application is handled by library or framework code. As Martin Fowler explains, even simple libraries such as Tk perform Inversion of Control ( Dependency injection is more specific form of Inversion of Control where the control flow that is being handled by the framework is how pluggable/swapable implementations are being chosen. Dependency Injection can be defined as, “the implementation of one class is performed partially by object(s) supplied by the framework”.

  4. Thanks Kevin,

    I would just like to add that there even gorilla patching has it’s uses. I fake out bits of SQLAlchemy during testing sometimes, and I’ve got a mokeypatched cherrypy wsgi server that we delivered to a client on a very tight deadline, and very specific requirements.

    And you are right to say that Inversion of Controll and Dependency Injection don’t require monkeypatching and are therefore totally seprate ideas — but they do provide use-cases for dynamically monkeying around with classes. I was not at all clear about that. ;)

  5. My definition of monkey patching is that it’s just a patch applied at runtime, with the emphasis on “patch” as defined in The Jargon File as “A temporary addition to a piece of code, usually as a quick-and-dirty remedy to an existing bug or misfeature.”

    Of course, that’s just my own understanding of monkey patching, lots of people have been using the term to mean dynamic modification to classes at runtime with other intents than as a patch. But two definitions of the term leaves it open for folks to get upset for no good reason though. If I say, “monkey patching is good for quick and dirty fixes” and I mean monkey patch *only* as “patch”, and someone else hears that and understands monkey patching to mean any type of dynamic class modification, then it sounds like I am saying, “dynamic class modification is only useful as a guick and dirty fix” – which isn’t true :(

    Take your example of faking out code for testing purposes. I may well find this to be an elegant, concise solution to your testing problem. But should it be called monkey patching if it’s intent is as a permanent solution?

Comments are currently closed.