Along the banks of the learning river I stumbled on 'monkey patching' during a particularly convoluted Javascript lecture...
WHAT IS MONKEY PATCHING?
Monkey patching is a way to extend, change or modify something (library, supporting system software, plugin) locally. This means applying a monkey patch won't change the library itself, but rather just the local copy of the library on your machine. 'Monkey Patching' is a term that merely means changing code at runtime. Most often this is done to work around a bug or feature.
(Oftentimes when an update comes out there are minor bugs that aren't devastating, but they make it a lot more frustrating to work through... hence the monkey patch.)
Monkey patching can be used to:
Replace methods / classes / attributes / functions at runtime (e.g. to stub out a function during testing)
Modify/extend behavior of a third-party product without maintaining a private copy of the source code
Apply the result of a patch at runtime to the state in memory, instead of the source code on disk
Distribute security or behavioral fixes that live alongside the original source code (an example of this would be distributing the fix as a plugin for the Ruby on Rails platform)
But monkey patching isn't only used to work around bugs. It can also be a way to modify behavior that isn't quite doing what we want. It's possible to make changes to said code using monkey patching.
FYI -- this only applies a patch to any original code. (Hence, 'monkey patching'.) It only applies to YOUR copy of it. Meaning, if you install a npm library, the monkey patch would only work on the library for you, and not directly modify the library npm has access to.
Here's an example of monkey patching, courtesy of Max Heiber:
They've monkey-patched 'Array' to add a 'last' method, which returns the last item in the array. Potential problems with this? Definitely. The author could change the implementation of 'last', which would break your code since yours relies on your implementation. Elsewhere in your code you (or someone else) will always have to remember that 'Array' has been patched. See how we're getting into little headaches?
So is it... wrong?
I knew I had to write a blog topic on it when I heard how it was discussed. Was it... horrible? In the end it's not... wrong, per se. Nor is it a particularly niche technique. But-- 9/10 times-- there's a better way to solve the issue. It's only in rare cases that monkey patching is the only (and best!) solution. Its rarity as 'best-use' is why it's discussed in such a taboo way.
Patches made to a module might not work after methods have changed and the module is updated. If monkey patches aren't applied conditionally, this can lead to crashes and bugs that are a headache to fix later on.
Also, if 2+ components apply a monkey patch to the exact same method-- depending on which component runs last-- the other monkey patch will be completely useless.
Monkey Patching Issues
Poorly documented or badly written patches can lead to a lot of possible problems:
Whenever a monkey patch relies on an assumption about the patched object, an upgrade can lead to problems if that assumption is no longer true after the upgrade is applied. Monkey patches should be made conditional, and then they can be applied only when appropriate.
"If two modules attempt to monkey patch the same method, one of them (whichever one runs last) "wins" and the other patch has no effect, unless monkey patches are written with a pattern like
alias_method_chain
They can create inconsistency between observed behavior of the application and the actual source code, which can lead to time wasted trying to debug an unfixable problem.
And-- obviously-- they can be written with malicious code inside.
References:
"New in Rails: Module#alias_method_chain". 2006-04-26.
Wikipedia: Monkey Patching
Max Heiber
Top comments (0)