Monkey-patching Vs. S.O.L.I.D. principles? - ruby

I'm slowly moving from PHP5 to Python on some personal projects, and I'm currently loving the experience. Before choosing to go down the Python route I looked at Ruby. What I did notice from the ruby community was that monkey-patching was both common and highly-regarded. I also came across a lot of horror stories regarding the trials of debugging ruby s/w because someone included a relatively harmless library to do a little job but which patched some heavily used core object without telling anyone.
I chose Python for (among other reasons) its cleaner syntax and the fact that it could do everything Ruby can. Python is making OO click much better than PHP ever has, and I'm reading more and more on OO principles to enhance this better understanding.
This evening I've been reading about Robert Martin's SOLID principles:
Single responsibility principle,
Open/closed principle,
Liskov substitution principle,
Interface segregation principle, and
Dependency inversion principle
I'm currently up to O: SOFTWARE ENTITIES (CLASSES, MODULES, FUNCTIONS, ETC.) SHOULD BE OPEN FOR EXTENSION, BUT CLOSED FOR MODIFICATION.
My head's in a spin over the conflict between ensuring consistency in OO design and the whole monkey-patching thing. I understand that its possible to do monkey-patching in Python. I also understand that being "pythonic" is to follow common, well-tested, oop best-practices & principles.
What I'd like to know is the community's opinion on the two opposing subjects; how they interoperate, when its best to use one over the other, whether the monkey-patching should be done at all... hopefully you can provide a resolution to the matter for me.

There's a difference between monkey-patching (overwriting or modifying pre-existing methods) and simple addition of new methods. I think the latter is perfectly fine, and the former should be looked at suspiciously, but I'm still in favour of keeping it.
I've encountered quite a few those problems where a third party extension monkeypatches the core libraries and breaks things, and they really do suck. Unfortunately, they all invariably seem stem from the the third party extension developers taking the path of least resistance, rather than thinking about how to actually build their solutions properly.
This sucks, but it's no more the fault of monkey patching than it's the fault of knife makers that people sometimes cut themselves.
The only times I've ever seen legitimate need for monkey patching is to work around bugs in third party or core libraries. For this alone, it's priceless, and I really would be disappointed if they removed the ability to do it.
Timeline of a bug in a C# program we had:
Read strange bug reports and trace problem to a minor bug in a CLR library.
Invest days coming up with a workaround involving catching exceptions in strange places and lots of hacks which compromises the code a lot
Spend days extricating hacky workaround when Microsoft release a service pack
Timeline of a bug in a rails program we had:
Read strange bug reports and trace problem to a minor bug in a ruby standard library
Spend 15 minutes performing minor monkey-patch to remove bug from ruby library, and place guards around it to trip if it's run on the wrong version of ruby.
Carry on with normal coding.
Simply delete monkeypatch later when next version of ruby is released.
The bugfixing process looks similar, except with monkeypatching, it's a 15 minute solution, and a 5-second 'extraction' whereas without it, pain and suffering ensues.
PS: The following example is "technically" monkeypatching, but is it "morally" monkeypatching? I'm not changing any behaviour - this is more or less just doing AOP in ruby...
class SomeClass
alias original_dostuff dostuff
def dostuff
# extra stuff, eg logging, opening a transaction, etc
original_dostuff
end
end

In my view, monkeypatching is useful to have but something that can be abused. People tend to discover it and feel like it should be used in every situation, where perhaps a mixin or other construct may be more appropriate.
I don't think it's something that you should outlaw, it's just something that the Ruby guys like to use. You can do similar things with Python but the community has taken the stance that things should be simpler and more obvious.

Monkey patching is not ruby-explicit, its done all over javascript too, with negative (IMO) effects.
My personal opinion is monkey patching should only be done to
a) Add functionality to an old version of a language which is available in the new version of the language which you need.
b) When there is no other "logical" place for it.
There are many many easy ways to make monkey patching really awful, such as the ability to change how basic functions such as ADDITION work.
My stance is, if you can avoid it, do so.
If you can avoid it in a nice way, kudos to you.
If you can't avoid it, get the opinion of 200 people because you probably just have not thought about it hard enough.
My pet hate is mootools extending the function object. Yes, you can do this. Instead of people just learning how javascript works:
setTimeout(function(){
foo(args);
}, 5000 );
There was added a new method to every function object, ( yes, im not joking ) so that functions now have their own functions.
foo.delay( 5000 , args );
Which had the additional effect of this sort of crap being valid:
foo.delay.delay( 500, [ 500, args ] );
And on like that ad infinitum.
The result? You no longer have a library, and a language, your langauge bows to the library and if the library happens to be in scope, you no longer have a language, and you cant just do things the way that they were done when you learn the language, and instead have to learn a new subset of commands just to not have it fall flat on its face ( at the cost of excessive slowdowns! )
may i note that foo.delay also returned an object, with its own methods, so you could do
x = foo.delay( 500, args );
x.clear();
and even
x.clear.delay(10);
which may sound overly useful, ... but you have to take into consideration the massive overhead used to make this viable.
clearTimeout(x);
SO HARD!
(Disclaimer: its been a while since I used moo, and have tried to forget it, and function names/structure may be incorrect. This is not an API reference. Please check their site for details ( sorry, their API reference sucks! ))

Mokeypatching is generally wrong. Create a proper subclass and add the methods.
I've used monkeypatching once in production code.
The issue is that REST uses GET, POST, PUT and DELETE. But the Django test client only offers GET and POST. I've monkeypatched methods for PUT (like POST) and DELETE (like GET).
Because of the tight binding between Django client and the Django test driver, it seemed easiest to monkeypatch it to support full REST testing.

You may find enlightening this discussion about Ruby's open classes and the Open-Closed Principle.
Even though I like Ruby, I feel monkey-patching is a tool of last resort to get things done. All things being equal, I prefer using traditional OO techniques with a sprinkle of functional programming goodness.

In my eyes, monkey-patching is one form of AOP. The article Aspect-Oriented Design Principles: Lessons from Object-Oriented Design (PDF) gives some ideas of how SOLID and other OOP principles can be applied to AOP.

My first thought is that monkey-patching violates OCP, since clients of a class should be able to expect that class to work consistently.

Monkey-patching is just plain wrong, IMHO. I've not come across the open/closed principle you mention before, but it's a principle I've long held myself, I agree with it 100%. I think of monkey-patching as a code-smell on a larger scale, a coding-philosophy-smell, as it were.

Related

Xcode "new method" shortcut?

My initial take on XCode is that it makes hard things easier, and easy things harder (find & replace requires way too many keystrokes, for example...). The biggest one to me, however is a lack of a method wizard... I tend to write lots of small methods, and I'm finding it hard to believe that you can't declare your method in a popup and have the interface and implementation files populated with stubs. Am I missing something? Frankly, I get far more functionality out of vi from an editor perspective.
I don't think you can do that exactly as you want it (without a plugin like Accessorizer), but it's not necessary, since you can create your own snippets, as highlighted in this snippet question, that will then contain the stubs you really need. Since most basic methods are written for you (or only require a few keywords to be autogenerated with your requirements, with #synthesize, etc...), it makes sense to me.
However, this could make your day if you still are unhappy :D

Does identifier casing really matter?

FxCop thought me (basically, from memory) that functions, classes and properties should be written in MajorCamelCase, while private variables should be in minorCamelCase.
I was talking about a reasonably popular project on IRC and quoted some code. One other guy, a fairly notorious troll who was also a half-op (gasp!) didn't seem to agree. Everything oughta be in the same casing, and he quite fervently favored MajorCamelCase, or even underscore_separation.
Ofcourse, he was just a troll so I reckoned I'd just keep doing it the way I already did. Before I learned the above guidelines, I hardly even had a coherent naming style.
He got me thinking, though -- does stuff like this really matter?
You need to make sure that your code is readable in the future. Please remember that you might want to pass the development of your application to someone else and this person will need to read and understand it. You could stop actively working on a project and return to it after a year - and be suprised that you have to read code carefully to understand how it works.
I believe it was Steve McConnell who said that specific naming style does not really matter (you could use anything you want as long as you are consistent) but this only applies when everyone working on the project agree with you.
In general it is better to adopt community-accepted coding styles where possible to facilitate code reuse and shorten learning curves.
If you don't care about long-term maintanability of your project (or consistency or readability) then no, casing (and coding conventions in general) don't really matter. Otherwise, they do matter. See this.
Your specific coding style doesn't matter (much), so long as it is consistent throughout the project.
This improves readability and understanding, as if an identifier is named in a particular way, the reader can (hopefully) be confident as to what that naming style implies.
As regards CamelCase v underscores, etc: again, it's down to your coding convention. One approach which uses both is to apply a prefix with underscore to indicate the module in which the function, or file-scope/global variable, is used, e.g. Config_Update(), Status_Get().

Good examples when teaching refactoring?

I'm running a refactoring code dojo for some coworkers who asked how refactoring and patterns go together, and I need a sample code base. Anyone know of a good starting point that isn't to horrible they can't make heads or tails of the code, but can rewrite their way to something useful?
I would actually suggesting refactoring some of your and your coworkers' code.
There are always places that an existing codebase can be refactored, and the familiarity with the existing code will help make it feel more like a useful thing and less like an exercise. Find something in your company's code to use as an example, if possible.
Here are some codes, both the original and the refactored version, so you can prepare your kata or simply compare the results once the refactoring is performed:
My books have both shorter examples and a longer, actually a book long example. Code is free to download.
VB Code Examples
C# Code Examples
A nice example from Refactoring Workbook
There are a lot of examples on the internet of simple games like Tic-Tac-Toe or Snake that have a lot of smells but are simple enough to start with refactoring.
The first chapter in Martin Fowler "Refactoring" is a good starting point to refactoring. I understood most of the concepts when one of my teachers at school used this example.
What is the general knowledge level of your coworkers?
Something basic as code duplication should be easy to wrap their heads around. Two pieces of (nearly) identical code that can be refactored into a reusable method, class, whatever. Using a (past) example from your own codebase would be good.
I would recommend you to develop a simple example project for a specific requirement.
Then you add one more requirement and make changes to the existing classes . You keep on doing this and show them how you are finding it difficult to make each change when the code is not designed properly. This will make them realize easily because, this is what those ppl will be doing in their day to day work. Make them realize that , if patterns and principles are not followed from beginning, how are they going to end up in mess at the end.
When they realize that,then you start from scratch or refactor the existing messed up code .Now add a requirement and make them realize that it is easy to make a change in the refactored code, so that you need to test only a few classes. One change would not affect others and so on.
You could use the computer ,keyboard and printer class as an example. Add requirements like, you will be wanting the computer to read from mouse , then one more requirement can be like your computer would want to save it in hard disk than printing. Finally your refactored code should be like, your computer class should depend on abstract input device class and output device class. And your keyboard class should inherit from Inputdevice class.
Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin considers refactoring.
I'm loving Refactoring Guru examples.
In there you can find design patterns examples too.
Refactoring is non-functional requirement when code perform correct functionality for which it is designed however difficult to debug, requires more effort to maintain and some performance bottleneck. Refactoring is to change to be easily maintainable, good readability and improve efficiency.
Thus we need to focus on criteria to make code more readable, easy to maintain.
Its obvious that having very large method/function might be difficult to understand.
Class depends on other hundreds of class make thing worst while debugging.
Code should be readable just like reading some workflow.
You can also use tools like sonar which can help you to identify critical criteria such as "Cyclomatic Complexity"
http://www.sonarsource.org/managing-cyclomatic-complexity-to-increase-maintainability/
You ask them to write code them self and check how tool does refactoring.
Apart from that, you can write code in eclipse and there is option available which does refactoring for you...
It's a bit dated (2003), but IBM has several refactoring examples (that work[ed?] in Eclipse) at http://www.ibm.com/developerworks/library/os-ecref/

Best way to get rid of hungarian notation?

Let's say you've inherited a C# codebase that uses one class with 200 static methods to provide core functionality (such as database lookups). Of the many nightmares in that class, there's copious use of Hungarian notation (the bad kind).
Would you refactor the variable names to remove the Hungarian notation, or would you leave them alone?
If you chose to change all the variables to remove Hungarian notation, what would be your method?
Refactor -- I find Hungarian notation on that scale really interferes with the natural readability of the code, and the exercise is a good way of getting familiar with what's there.
However, if there are other team members who know the code base you would need consensus on the refactoring, and if any of the variables are exposed outside of the one project then you will have to leave them alone.
Just leave it alone. There are better uses of your time.
Right click on the variable name, Refactor -> Rename.
There are VS add-ins that do this as well, but the built-in method works fine for me.
What would I do? Assuming that I just have to maintain the code and not rewrite it any significant way? Leave it well alone. And When I do add code, go with the existing style, meaning, use that ugly Hungarian notation (as dirty as that makes me feel.)
But, hey, if you really have a hankerin' fer refactorin' then just do a little at a time. Every time you work on it spend ten minutes renaming variables. Tidying things up a little. After a few months you might find it's clean as a whistle....
Don't forget that there are two kinds of Hungarian Notation.
The original Charles Simonyi HN, later known as App's Hungarian and the later abomination called System Hungarian after some peckerhead (it's a technical term) totally misread Simonyi's original paper.
Unfortunately, System HN was propagated by Petzold and others to become the more dominant abortion that it is rightfully recognised as today.
Read Joel's excellent article about the intent of the original Apps Hungarian Notation and be sorry for what got lost in the rush.
If what you've got is App's Hungarian you will probably want to keep it after reading both the original Charles Simonyi article and the Joel article.
If you've landed in a steaming pile of System Hungarian?
All bets are off!
Whew! (said while holding nose) (-:
if you're feeling lucky and just want the Hungarian to go away, isolate the Hungarian prefixes that are used and try a search and replace in file to replace them with nothing, then do a clean and rebuild. If the number of errors is small, just fix it. If the number of errors is huge, go back and break it up into logical (by domain) classes first, then rename individually (the IDE will help)
I used to use it religiously back in the VB6 days, but stopped when VB.NET came out because that's what the new VB guidelines said. Other developers didn't. So, we’ve got a lot of old code with it. When I do maintenance on code I remove the notation from the functions/methods/sub I touch. I wouldn't remove it all at once unless you've got really good unit tests for everything and can run them to prove that nothing's broken.
How much are you going to break by doing this? That's an important question to ask yourself. If there are a lot of other pieces of code that use that library, then you might just be creating work for folks (maybe you) by going through the renaming exercise.
I'd put it on the list of things to do when refactoring. At least then everyone expects you to be breaking the library (temporarily).
That said, I totally get frustrated with poorly named methods and variables, so I can relate.
I wouldn't make a project out of it. I'd use the refactoring tools in VS (actually, I'd use Resharper's, but VS's work just fine) and fix all the variables in any method I was called upon to modify. Or if I had to make larger-scale changes, I'd refactor the variable names in any method I was called upon to understand.
If you have a legitimate need to remove and change it I would use either the built in refactoring tools, or something like Resharper.
However, I would agree with Chris Conway to a certain standpoint and ask you WHY, yes, it is annoying, but at the same time, a lot of the time the "if it aint't broke done't fix it" method is really the best way to go!
Only change it when you directly use it. And make sure you have a testbench ready to apply to ensure it still works.
I agree that the best way to phase out hungarian notation is to refactor code as you modify it. The greatest benefit of doing this kind of refactoring is that you should be writing unit tests around the code you're modifying so that you have a safety net instead of crossing your fingers and hoping that you don't break existing functionality. Once you have these unit tests in place, you are free to change the code to your heart's content.
I'd say a bigger problem is that you have a single class with 200(!) methods!
If this is a much depended on / much changed class then it might be worth refactoring to make it more usable.
In this, Resharper is an absolute must (you could use the built in refactoring stuff, but Resharper is way better).
Start finding a group of related methods, and then refactor these out into a nice small cohesive class. Update to conform to your latest code standards.
Compile & run your test suite.
Have energy for more? Extract another class.
Worn out - no trouble; come back and do some more tomorrow. In just a few days you'll have conquered the beast.
I agree with #Booji -- do it manually, on a per-routine basis when you're already visiting the code for some other good reason. Then, you'll get the most common ones out of the way, and who cares about the rest.
I was thinking of asking a similar question, only in my case, the offending code is my own. I have a very old habit of using "the bad kind" of Hungarian from my FoxPro days (which had weak typing and unusual scoping) — a habit I've only recently kicked.
It's hard — it means accepting an inconsistent style in your code base. It was only a week ago I finally said "screw it" and began a parameter name without the letter "p". The cognitive dissonance I initially felt has given way to a feeling of liberty. The world did not come to an end.
The way I've been going about this problem is changing one variable at a time as I come across them, then perform more sweeping changes when you come back to do more in-depth changes. If you're anything like me, the different nomenclature of your variables will drive you bat-shiat crazy for a while, but you'll slowly become used to it. The key is to chip away at it a little bit at a time until you have everything to where it needs to be.
Alternatively, you could jettison your variables altogether and just have every function return 42.
It sounds to me like the bigger problem is that 200-method God Object class. I'd suggest that refactoring just to remove the Hungarian notation is a low-value, high-risk activity in of itself. Unless there's a copious set of automated unit tests around that class to give you some confidence in your refactoring, I think you should leave it well and truly alone.
I guess it's unlikely that such a set of tests exists, because a developer following TDD practices would (hopefully) have naturally avoided building a god object in the first place - it would be very difficult to write comprehensive tests for.
Eliminating the god object and getting a unit test base in place is of higher value, however. My advice would be to look for opportunities to refactor the class itself - perhaps when a suitable business requirement/change comes along that necessitates a change to that code (and thus hopefully comes with some system & regression testing bought and paid for). You might not be able to justify the effort of refactoring the whole thing in one go, but you can do it piece by piece as the opportunity comes along, and test-drive the changes. In this way you can slowly convert the spaghetti code into a cleaner code base with comprehensive unit tests, bit by bit.
And you can eliminate the Hungarian as you go, if you like.
I am actually doing the same thing here for an application extension. My approach has been to use VIM mappings to search for specific Hungarian notation prefixes and then delete them and fix capitalization as appropriate.
Examples (goes in vimrc):
"" Hungarian notation conversion helpers
"" get rid of str prefixes and fix caps e.g. strName -> name
map ,bs /\Wstr[A-Z]^Ml3x~
map ,bi /\Wint[A-Z]^Ml3x~
"" little more complex to clean up m_p type class variables
map ,bm /\Wm_p\?[A-Z]^M:.s/\(\W\)m_p\?/\1_/^M/\W_[A-Z]^Mll~
map ,bp /\Wp[A-Z]^Mlx~
If you're gonna break code just for the sake of refactoring, I would seriously consider leaving i alone, specially, if you are going to affect other people in your team who may be depending on that code.
If your team is OK with this refactoring, and investing your time in doing this (which may be a time-saver in the future, if it means the code is more readable/maintainable), use Visual Studio (or whatever IDE you are using) to help you refactor the code.
However, if a big change like this is not a risk your team/boss is willing to take, I would suggest a somewhat unorthodox, half-way approach. Instead of doing all your refactoring in a single sweep, why not refactor sections of code (more specifically, functions) that need to be touched during normal maintenance? Over time, this slow refactoring will bring the code up to a cleaner state, at which point you can finish the refactoring process with a final sweep.
Use this java tool to remove HN:
Or just use "replace"/"replace all" with regex like below to replace "c_strX" to "x":
I love Hungarian notation. Don't understand why you would want to get rid of it.

How can I program defensively in Ruby?

Here's a perfect example of the problem: Classifier gem breaks Rails.
** Original question: **
One thing that concerns me as a security professional is that Ruby doesn't have a parallel of Java's package-privacy. That is, this isn't valid Ruby:
public module Foo
public module Bar
# factory method for new Bar implementations
def self.new(...)
SimpleBarImplementation.new(...)
end
def baz
raise NotImplementedError.new('Implementing Classes MUST redefine #baz')
end
end
private class SimpleBarImplementation
include Bar
def baz
...
end
end
end
It'd be really nice to be able to prevent monkey-patching of Foo::BarImpl. That way, people who rely on the library know that nobody has messed with it. Imagine if somebody changed the implementation of MD5 or SHA1 on you! I can call freeze on these classes, but I have to do it on a class-by-class basis, and other scripts might modify them before I finish securing my application if I'm not very careful about load order.
Java provides lots of other tools for defensive programming, many of which are not possible in Ruby. (See Josh Bloch's book for a good list.) Is this really a concern? Should I just stop complaining and use Ruby for lightweight things and not hope for "enterprise-ready" solutions?
(And no, core classes are not frozen by default in Ruby. See below:)
require 'md5'
# => true
MD5.frozen?
# => false
I don't think this is a concern.
Yes, the mythical "somebody" can replace the implementation of MD5 with something insecure. But in order to do that, the mythical somebody must actually be able to get his code into the Ruby process. And if he can do that, then he presumably could also inject his code into a Java process and e.g. rewrite the bytecode for the MD5 operation. Or just intercept the keypresses and not actually bother with fiddling with the cryptography code at all.
One of the typical concerns is: I'm writing this awesome library, which is supposed to be used like so:
require 'awesome'
# Do something awesome.
But what if someone uses it like so:
require 'evil_cracker_lib_from_russian_pr0n_site'
# Overrides crypto functions and sends all data to mafia
require 'awesome'
# Now everything is insecure because awesome lib uses
# cracker lib instead of builtin
And the simple solution is: don't do that! Educate your users that they shouldn't run untrusted code they downloaded from obscure sources in their security critical applications. And if they do, they probably deserve it.
To come back to your Java example: it's true that in Java you can make your crypto code private and final and what not. However, someone can still replace your crypto implementation! In fact, someone actually did: many open-source Java implementations use OpenSSL to implement their cryptographic routines. And, as you probably know, Debian shipped with a broken, insecure version of OpenSSL for years. So, all Java programs running on Debian for the past couple of years actually did run with insecure crypto!
Java provides lots of other tools for defensive programming
Initially I thought you were talking about normal defensive programming,
wherein the idea is to defend the program (or your subset of it, or your single function) from invalid data input.
That's a great thing, and I encourage everyone to go read that article.
However it seems you are actually talking about "defending your code from other programmers."
In my opinion, this is a completely pointless goal, as no matter what you do, a malicious programmer can always run your program under a debugger, or use dll injection or any number of other techniques.
If you are merely seeking to protect your code from incompetent co-workers, this is ridiculous. Educate your co-workers, or get better co-workers.
At any rate, if such things are of great concern to you, ruby is not the programming language for you. Monkeypatching is in there by design, and to disallow it goes against the whole point of the feature.
Check out Immutable by Garry Dolley.
You can prevent redefinition of individual methods.
I guess Ruby has that a feature - valued more over it being a security issue. Ducktyping too.
E.g. I can add my own methods to the Ruby String class rather than extending or wrapping it.
"Educate your co-workers, or get better co-workers" works great for a small software startup, and it works great for the big guns like Google and Amazon. It's ridiculous to think that every lowly developer contracted in for some small medical charts application in a doctor's office in a minor city.
I'm not saying we should build for the lowest common denominator, but we have to be realistic that there are lots of mediocre programmers out there who will pull in any library that gets the job done, paying no attention to security. How could they pay attention to security? Maybe the took an algorithms and data structures class. Maybe they took a compilers class. They almost certainly didn't take an encryption protocols class. They definitely haven't all read Schneier or any of the others out there who practically have to beg and plead with even very good programmers to consider security when building software.
I'm not worried about this:
require 'evil_cracker_lib_from_russian_pr0n_site'
require 'awesome'
I'm worried about awesome requiring foobar and fazbot, and foobar requiring has_gumption, and ... eventually two of these conflict in some obscure way that undoes an important security aspect.
One important security principle is "defense in depth" -- adding these extra layers of security help you from accidentally shooting yourself in the foot. They can't completely prevent it; nothing can. But they help.
If monkey patching is your concen, you can use the Immutable module (or one of similar function).
Immutable
You could take a look at Why the Lucky Stiff's "Sandbox"project, which you can use if you worry about potentially running unsafe code.
http://code.whytheluckystiff.net/sandbox/
An example (online TicTacToe):
http://www.elctech.com/blog/safely-exposing-your-app-to-a-ruby-sandbox
Raganwald has a recent post about this. In the end, he builds the following:
class Module
def anonymous_module(&block)
self.send :include, Module.new(&block)
end
end
class Acronym
anonymous_module do
fu = lambda { 'fu' }
bar = lambda { 'bar' }
define_method :fubar do
fu.call + bar.call
end
end
end
That exposes fubar as a public method on Acronyms, but keeps the internal guts (fu and bar) private and hides helper module from outside view.
If someone monkeypatched an object or a module, then you need to look at 2 cases: He added a new method. If he is the only one adding this meyhod (which is very likely), then no problems arise. If he is not the only one, you need to see if both methods do the same and tell the library developer about this severe problem.
If they change a method, you should start to research why the method was changed. Did they change it due to some edge case behaviour or did they actually fix a bug? especially in the latter case, the monkeypatch is a god thing, because it fixes a bug in many places.
Besides that, you are using a very dynamic language with the assumption that programmers use this freedom in a sane way. The only way to remove this assumption is not to use a dynamic language.

Resources