Monkey patching is modifying a third-party class. It’s a great tool, coming in handy all the time. Only it’s frowned upon by the experienced programmers. Should you adopt or abandon monkey patching?
Let’s have a look at some useful applications of monkey patching first.
Why is monkey patching useful?
My favorite example is written in the Groovy language. It combines monkey patching and the fact that even simple integer numbers are objects in Groovy. So you can add methods like
meter, and probably even
ångstrøm() to the
Double class and write code like this:
// Java-like coding style: System.out.println(1.mile() + 500.meter()); // equivalent, more relaxed coding style: println 1 mile + 500 meter
When I was writing software for the financial industries, I missed this feature badly. It’s hard to calculate with money and currencies if you have to convert everything to an object first. Just try to jot down a formula with simple numeric values, and repeat the same exercise with Java’s
BigDecimal again. You’ll notice the difference painfully.
Other use cases of Monkey patching
Actually, Monkey patching refers to two slightly different ideas:
- You can augment an existing class. You can add methods and attributes. That’s what we did above when we added
- You can modify a method of an existing class.
At first glance, the second idea is irresistible. Do you have to work with a third-party library that’s buggy? With monkey patching, that’s not a big deal. Just apply a Monkey patch to it, and it’s as good as new.
Risks of patching a third-party library
There’s a catch. What happens when the bug of the third-party library has been solved? If you’re lucky (or well organized), you remember to remove your patch. But there are no guarantees.
Actually, that’s also true with other workarounds, such as encapsulating the offending library in a class fixing the bug. The problem with Monkey patching is that it also affects the code using the offending library directly. This may include code written by your co-workers in the neighbor department and even other third-party libraries.
Basically, that’s already the morale of the story. Monkey patching is a tool that’s just a bit too powerful. It affects everything, including uses you didn’t think of at the time of writing.
But adding functionality is good, isn’t it?
Another popular use of Monkey patching is adding methods to existing classes. For instance, until ECMAScript 2015, there was no
In fact, it became so popular that the ECMAScript team decided to rename their
contains() method to
includes(). If they were to add their own implementation of
contains() amounts to breaking zillions of existing websites. The semantics of the ECMAScript specification differs slightly from the Mootools implementation. Plus, the Mootools have been implemented in a conservative way: it only adds
contains() if it isn’t already there. That sounds like a good idea: there’s no point in patching a method that’s already been patched. However, in combination, these two facts would break existing code. It’d be better if the Mootools simply overwrote the new ECMAScript method.
In this particular case, Monkey patching even interfered with the development of the programming language.
You get the gist of it. Monkey patching is a powerful tool, but it’s just a bit too powerful. If you need it, think again. You’re about to add non-standard behavior to your code base. That’s exactly the kind of surprises you’d rather avoid. Your co-worker who’s going to maintain your code next year will love you for that.
Other developers have the same idea
Another risk is that other programmers probably had the same idea. If you’re Monkey patching a method, chances are one of the libraries you’re using also patches the same method.
Which implementation is going to be executed? More likely than not, that’s unpredictable. Plus, if you’re patching a method that’s patched by someone else, too, their patch isn’t applied. So the third-party library you’re using probably breaks.
When to use Monkey patching – and when not to use it
- Never use Monkey patching in a library.
- Never use Monkey patching to repair a third-party library.
- If you can’t avoid patching a third-party library, do it in a careful way. Scream it out in your documentation, mention it in the log files, and add a version check. Even so, it’s a risky game.
- On the other hand: if you’re a solo programmer in a short-lived project, go for it!
- The same applies if you’re reasonably sure you’re additions will never interfere with any third-party library or the future versions of your programming language. There’s no way to be sure, but I’d wager adding currencies,
meter()is on the safe side, just to name a few examples.
console.error(), and so on. I’m sure there’s more benefit than risk. But when I investigated for this article (and the task at hand), I learned that many other programmers had the same idea, and it didn’t pay out for all of them.
Wrapping it up
Monkey patching is like a drug. At first glance, it’s obviously the way to go. There are side effects, but they tend to show up a year or two later. So think twice before applying a Monkey patch.
But then – it’s true that sharp knives cut, but tell this a surgeon. There’s a place and a time for everything!
Gilad Bracha on Monkey patching
Aurelio de Rose on Monkey patching
Wikipedia on Monkey patching (regard the “pitfalls” section)
Pragmatic uses of Monkey patching by Vildan Softic
Monkey patching for mere mortals