A monkey patch is a way to extend or modify the runtime code of dynamic languages (e.g. Smalltalk, JavaScript, Objective-C, Ruby, Perl, Python, Groovy, etc.) without altering the original source code. -- WikipediaTill tried to do some monkey patching a while ago, using PHP namespaces. Basically, if you use a PHP function inside a namespace, the original function will be called if an override is not defined. In the example, calling strlen() inside of a namespace would refer to the NamespaceName\strlen() function, and if it not exists, it would fall back to PHP's native one.
The problem was that you actually have to namespace the original code. It would not be monkey patching anymore: if I could modify that code, I would simply change the function calls.
For example, we may want to monkey patch the following code:
<?php $str = 'mystring'; echo "This should eight, but it's not: " . strlen($str) . "\n"; // 6So what do we do? Basically, this evil black magic:
<?php namespace monkeypatching; function strlen() { return 6; } $code = file_get_contents('monkeypatched.php'); $code = 'namespace monkeypatching; ?> ' . $code; echo $code; eval($code);which prints out:
This should eight, but it's not: 6Of course this infringes every single SOLID and software engineering principle. Again, don't code like this, we are not in Ruby.
In general, methods and functions definitions are part of the mandatory global state of an application, and so once the loading phase has finished they should be immutable. This is done at the loading time, so it may be acceptable. But also dangerous: it's the poor man's version of polymorphism.
there's a discussion on the grusp mailing list defining when monkey patching is a good practice
ReplyDeleteAlso, for purposes of testing legacy code, it seems like a very nice seam.
ReplyDeleteYou really should give a better explanation of why one shouldn't do this. There are a handful of places where monkey patching is appropriate and if you are going to give advice as to whether people should or shouldn't engage in a practice then you should give a good (read well supported) reason for it.
ReplyDeleteThere are many reasons for avoiding monkey patching:
ReplyDeletehttp://en.wikipedia.org/wiki/Monkey_patch#Pitfalls
However, the greatest issue for me is the global state modifications implied by monkey patching and the Action at a distance anti-pattern that results. Once you start modifying the library functions, code in other modules and classes will began to work differently. This article describes a way to use the seam at loading/compile time, but it seems pretty dangerous nonetheless: think about one programmer unaware of the patching going on who sees this output: he would never question the correctness of a PHP function, leading to an awful debugging session...
Why the 'echo' before the 'eval'?
ReplyDeleteTo show the code actually executed (with the addition of the namespace). Not necessary, but explanatory. :)
ReplyDeleteThere is runkit extension for true monkey patching: http://www.php.net/manual/en/intro.runkit.php
ReplyDelete