Monkeypatch if you must, but do it responsibly

Monday July 14, 2008 @ 01:06 PM (PDT)

Jeff Atwood recently posted some thoughts on monkeypatching. Strangely, he only writes about one aspect of monkeypatching—modifying the functionality of a core language feature—and makes no mention of the much less dangerous and far more common use case, which is to modify the functionality of a third-party library.

As Jeff points out, monkeypatching a core language feature is almost always a bad idea because the changes propagate to all running code rather than just your code. This is an excellent way to virtually guarantee strange, hard to debug problems, especially if you’re writing an application that uses one or more third-party libraries or frameworks. On the other hand, monkeypatching third-party code is usually less dangerous and the effects are easier to control, since your changes will only affect code that uses that particular library.

Before monkeypatching, you should always exhaust all other options in the following order:

  1. If the change can be implemented in a reasonably elegant way without monkeypatching, do it that way (especially if it’s a change to a core language feature).
  2. If the library or framework you want to change is open source and your change would benefit other users, make your change there and contribute it to the project as a normal patch.
  3. If neither option is possible, then you may monkeypatch, but do so in as limited and careful a fashion as you can. Make the patch obvious; don’t hide it in the midst of a bunch of other code.

In all the open source code I’ve written to date, I’ve only ever needed to use a monkeypatch once. The patch in question is in Thoth, and it makes a very small change to the way Ramaze looks for a requested static file.

I implemented this as a monkeypatch because the feature is of limited use to most other Ramaze users and would have required significant changes to Ramaze if implemented in a generic way rather than in a way specific to Thoth’s needs. The patch is very limited in its scope; it only affects the instance of Ramaze on which Thoth—and nothing else—is running.

Even so, I still revisit this code every so often to reevaluate whether it should remain a monkeypatch or be added to Ramaze.

Comments

Number.prototype.hexMyAssUp = function() {
     return this.toString(16);
}

var wee = 255;
alert(wee.hexMyAssUp());

Everyone be sure to extend Object, too.

Matt, you’re obviously not patching hard enough. True monkeypatching is best done in Ruby (or Scheme!), and should make use of techniques like recursive lambda, automated overloaded method chaining (‘perform_x_without_y_validation_without_z_widgiteering()’), or nested evals.

There’s a fine line between monkeypatching and ninja patching, and I think that crosses it.

Extra points for monkeypatching the monkeypatching code that’s part of a third-party library. Yes, Rails, I’m looking at you. :-)

Copyright © 2002-2012 Ryan Grove. All rights reserved.
Powered by Thoth.