Ruby's Open Classes - Or: How Not To Patch Like A Monkey
Eric Anderson
by
Eric Anderson
I take away the opposite lesson from the Symbol#to_proc incompatibility problem. What I take away is "use open classes (within reason) because it will give you great functionality that you need without waiting for some official vendor to support it".
Don't get my wrong. Alternatives should certainly be considered. Open classes are not the solution for every problem and your article lists and explains some great alternatives. But don't be scared of open classes either.
Rails popularized the Symbol#to_proc method and it may not have been included in Ruby 1.9 and backported to Ruby 1.8 had Rails not popularized it. Symbol#to_proc is an extremely useful method that has saved countless developers countless snippets of time. By having open classes Rails was able to include this functionality YEARS before some official vendor supported it. Even once the vendor did support it there was a slight incompatibility which was resolved. Now each case is different. This time the issue was resolved by the official vendor changing their code. Maybe next time the application (or framework) will need to change it's code to get the issue resolved. But either way we traded countless amounts of time saved for just a few moments of "hmmm.... I guess we need to change this to that". Sounds like a big win for me.
Stop being afraid of the dynamic language and embrace it. Have good testing to catch issues like this before deployment and then love the benefits you reap. Don't go back to the old non-agile way of doing things where you write reams of extra convoluted code just to ensure you are not affected by some unlikely issue that might happen in the future.
You are going to have compatibility problems no matter how careful you are. So just use common sense and deal with anything when it comes.
Overstated as Written
by
Christian Romney
Only for "clients" in that process or that require the offending library. The way it's written - and with system in italics - it sounds like you can hose the standard library for all Ruby applications running on a box by using open classes.
Patch like a Monkey
by
Kevin Teague
There is also a "monkey" package for Python which only applies the patch if a hash signature of the patched method is unchanged, which is an extra careful way of patching so that the developer can be alerted when the upstream source being patched has changed (pypi.python.org/pypi/monkey).
Monkey patching was originally called "guerilla patching" (a term started at Zope Corp.) because a developer who disagreed with a choice made upstream could apply their own behaviour without needing to have the patch reviewed and applied upstream. Guerilla patching was misheard as Gorilla patching and from that the term Monkey patching was invented to sound "less forceful than a gorilla". Zope developers still tend to use this term to only apply to opening classes to fix or extend them to address undesirable behaviour upstream - other use-casses for re-opening a class is usually just called "dynamic class modification". However, in the larger Python and Ruby communities this distinction isn't usually made and Monkey patching usually refers to any re-opening of class, regardless of intent.
The adapter pattern developed in Zope (and the convention-over-configuration technique applied by Grok which avoids the need for XML sit-ups) rocks, and is better alternative in many cases than the venerable monkey patch. Syntactically Python adaptation is much more concise than the Java equivalent :)
Eclipse/Java:
OutlinePage p = editor.getAdapter(OutlinePage.class);
Zope/Python:
p = IOutlinePage(editor)
BTW, it's Zope and not ZOPE, which is akin to saying RUBY or JAVA, all-caps are yucky :P
Re: Overstated as Written
by
Werner Schuster
Re: Eric Anderson
by
Werner Schuster
BTW: experimentation like this is fine enough - that doesn't mean that you want to put something like this in a library. We recently had a presentation on how Mingle was built:
www.infoq.com/presentations/ford-rails-based-mi...
One thing that I noticed was the liberal use of Open Classes - something which is fine if you build an application which is _never_ going to be part of something else.
However: if you release a library, you have no idea at all where it'll end up and with which other libraries it'll share an address space.
How would you like it if you just spent a day or two tracking down a problem... only to find out that developers of library A had to slap some odd method on Object, just to save a few keystrokes.
There is, however, the issue that it's very easy to use open classes... and it's very easy to ignore the very real issues.
Mind you: there are ways to avoid these issues _AND_ reap the benefits - I gave a few solutions in other languages (Classboxes, Extension Methods), and there are more which come as a neat side effect of strict enforcement of modularity: eg.
gbracha.blogspot.com/2008/03/monkey-patching.html
Or watch Gilad Bracha's talk on Newspeak:
www.cincomsmalltalk.com/blog/blogView?showComme...
So, yeah: use Open Classes... just don't patch like a monkey...
Educational Content
Intro to CLP with core.logic
Ryan Senior Jun 18, 2013
Spock: A Highly Logical Way To Test
Howard Lewis Ship Jun 18, 2013
Java Garbage Collection Distilled
Martin Thompson Jun 17, 2013
C++11 The Future is Here
Bjarne Stroustrup Jun 16, 2013
The Big Data Revolution
Claudia Perlich Jun 16, 2013




Hello stranger!
You need to Register an InfoQ account or Login to post comments. But there's so much more behind being registered.Get the most out of the InfoQ experience.
Tell us what you think