Leo's Technical Blog

On Really Disliking Monkeypatching

Introduction

user

Leo Soto


rants, rails

On Really Disliking Monkeypatching

Posted by Leo Soto on .
Featured

rants, rails

On Really Disliking Monkeypatching

Posted by Leo Soto on .

No, this is not going to be a very well articulated post. I'm just ranting, expecting that I can feel better in a few more minutes and get back to work.

I hate monkey-patching. Yeah, yeah, I also use it when there is no other option, but I still hate it while using it. It's a last-resort tool, damn it.

But Rails guys seems to like it. Or Ruby guys, I don't know, because most of my Ruby experience is with Rails. But I want to separate "Ruby-culture" from "Rails-culture" so I can jump in the Rails-hating bandwagon without painting myself on a corner with respect to Ruby usage ;-)

Anyway, I'm ranting right now because I'm being hurt by monkey-patching right now. And it's not the typical "Heck, where is this damn method really defined", which is why most people end up disliking monkey-patching.

This time was: "What the hell, this Rails application doesn't work anymore?". But we have not touched anything in the last, hmm, 10 months! Let's see, what's new on this server, well a new point release of ruby, new point release of PostgreSQL and we know that couldn't possible break it. So better ask google, and... it turns up that the new point release of Ruby triggered the problem. WTF!

But how could a new method break old code? Name clashes introduced by monkey-patching, of course!. In Ruby 1.8.7 the String class introduced the String#chars method, which was also something Rails (or, technically, Activesupport) monkey-patched into the class in the past. Worst of all, both methods have different interfaces (specifically different return types), so it just boom!.

Anyway, this particular issue is not a problem in the 2.x series of Rails, where the issue was fixed some months ago. But this application was written with Rails 1.2.x, so bad luck for us.

[For correctness sake, I should admit that dynamically creating a new method on a class wasn't called monkey-patching in the original sense of the term, because it doesn't patch an existing feature of the class. But the problems with dynamically-adding-methods-to-other-classes and monkey-patching are more or less equivalent, thus using the shorter, familiar "monkey-patching" term sounded good to me]

Update: Here is more constructive post on the same specific problem. And seems like 2.0.x is also affected by the problem as only 2.1.x got the fix.