The problem with monkeypatching is simple : we can’t be sure we will call the “good” method, because the “good” one might be redefined by an other library…
Thus, I see only one simple solution : separating the methods.
impressive, isn’t it ?
Actually, we can separate methods in 3 places :
- when we define them
- when we call them
- at any time between this 2 places ;)
Redefining a method erase the original, so I think the third solution is impossible.
The second solution seems to be really bad (dropping the OOP advantages).
So let see the first one.
I’ve seen a library allowing to create several environments and require “bad” libraries, one by environment. So it’s possible to require 2 incompatible libs, and use the class. It seems to be interesting but to complex, and I don’t like to split my class in 2 versions…
So the stupid idea, which regroups the first and second solution, would be to force to use different names for each methods :/
Imagine, when you create a module, all its methods have for real name moduleName___method_name.
Ok this is too radical, and ugly ([1,2,3].Enumerable___collect{...}).
So imagine, we have a similar syntax (ModuleName::method_name) which will automatically lookup the method method_name of module ModuleName (if it’s an ancestor…
Thus [].collect will be same as [].Enumerable::collect.
Ok what is the advantage ?
When you use other’s methods, you see no difference.
When you use your methods, if you use the extended notation, you are sure there are no ambiguity in the module name.
Maybe this type of calls can be faster :)
Thus, we have simplicity and we avoid the problem of incompatible libraries…
Method namespace may not be the best solution of the monkeypatching problem, but I suppose it could be a good answer.