Monkeypatching For Humans

I have the same feelings about this topic. Monkeypatching is really powerful and tempting, but on the other side it’s a really dangerous technique. Simply spoken, power corrupts. The more power a programmer gets, the more he is responsible to use this power in the right way. I think there are very few use cases where monkeypatching should be preferred to conventional means. But sometimes its really useful, e.g. in the context of codegeneration (and especially for programs that are not too big).

Oh it happened to me once in a huge JavaScript file, where I accidentally redefined window…it took me hours to track that!

Your Left function blows up if the string is null, which is cool if you intended that, but I thought I might mention it to anyone copying your function. I wrote a similar function when I was copying a VB program into C#.

In order to change the function, you would put this as the first line:

if (s == null)
return null;

As to the matter at hand, I agree that extension methods are pretty scary in the wrong hands. It’s definitely something to think about.

I have already had a talk with all the C# programmers where I work and we have agreed that we will only use them to add functionality that would commonly be associated with a class of that type generically, like your left method.

Anything specific to a class or a project should not be an extension method.

Because of monkey patching I’m VERY biased against Ruby right now. My introduction to Ruby was through a very complicated program, written by some consultants. That thing was atrocious, and used monkey patching like it was going out of style. For example, anything remotely related to Arrays was added to the Array class. You need to count the number of red cars in an array of mixed objects? Call Array.CountRedCars! Sure, you COULD create a class for car arrays, but that would just make things TOO EASY.

I’m sure Ruby is a very respectable language. The kids sure like it. But that program left such a bad taste in my mouth that I wont touch it again if I don’t have to.

(I’ve probably got my syntax wrong, but that’s okay)

Where did you get that beautiful monkey image from?

Regardless of the extension technique, be it monkeypatching, overloading, or runtime, binary self-modification, it’s never the language’s fault; it’s the community’s.

Ruby’s is one of those few communities where you get to see both good and bad sides of monkeypatching. Application-level plugging ala Rails is good. Language-level plugging in Gems, no matter how well-documented, is usually bad.

But hey, if we’re going to abuse the power no matter what, then we might as well do it with a big sinister smile, knowing that Joe Rookie can never take on a job debugging it.

Perhaps this could raise another question: is there benefit from using a dynamic feature of the language when an equivalent static feature exists?

Static or compile time usually mean that important information about a program’s behaviour can be inferred from a program’s text alone without having to actually run the program to determine what a line of code does.

This idea of determining a program’s behaviour from reading it goes back to the days of Goto statement considered harmful.

I admit that we need dynamic language features at various points in a program and that they certainly have their role in making code more expandable or even more understandable, but we need to keep in mind the understandability tax that we might sometimes need to pay when using them.

I don’t think the C# language designers will succumb to the madness of allowing full monkey patching. It would be very difficult, if not impossible, to implement in the CL anyway.

By the way, bugs like the one with inherited() would immediately show up when stepping through the code with a debugger, right? Proper tools are so important… and most dynamic languages are gravely lacking proper tooling. This is partly because it’s so difficult to implement things like code completion when nearly everything depends on the runtime behaviour of your program.

Is it possible to clearly identify whether a method has been monkeypatched?

In the C# example I guess by advent of its presence in the current class you’d know you were extending the class, but I wonder in multi-dev environments how a developer would know that another has added an extension method within the designer (instead of having to email or IM someone).

One other thing, OT - over the last couple of weeks I’ve noticed lots of first posts. I dont know if its a testament to the blog’s increasing popularity, but its freakin’ annoying.

actually there’s no monkeypatching in Python

Gary:

My introduction to _____ was through a very complicated program, written by some consultants. That thing was atrocious, and used _____ _____ like it was going out of style… I’m sure _____ is a very respectable language… But that program left such a bad taste in my mouth that I wont touch it again if I don’t have to.

You know, I could tell almost EXACTLY the same story about several different languages and applications written by consultants. I suspect that when someone is paid $250 an hour to write an application, he feels compelled to make it buzzword-compliant.

And you know what? At one time the kids sure liked PCs, and BASIC, and Java, and C, and then C++… I suspect you were trying to be dismissive, but in my experience, dismissing something because the people who use it make you feel old can backfire, badly. be careful out there.

One other thing, OT - over the last couple of weeks I’ve noticed lots of first posts. I dont know if its a testament to the blog’s increasing popularity, but its freakin’ annoying.

Hey I am tenth!

Too right about it being annoying!

This reminds me of Aspect Oriented Programming. It faces the same difficulty. You have to be very careful with your ascpects because debugging is suddenly a whole lot scarier.

Unlike Ruby, you can’t monkeypatch the builtin types in Python. (You can also protect your own classes from monkey patching if you want).

You can shadow builtins or patch your own classes / extensions if you want.

The actual term monkey patching comes from the Python community (from the Zope community so the legend goes - where it originated as ‘guerilla patching’). Within the Python world the term is definitely pejorative…

@PRMan

That’s a terrible idea. You want to know as soon as possible when you have a null. If you consistently write code like that, when the time comes that you truly need a non-null value it will blow up so far away from where the null was originally introduced it will be incredibly difficult to find it.

@Alisic

Sure there is.

class A:
  def f(self):
  return I'm an A.

old_f = A.f
def new_f(self):
  return old_f(self) +  or so he thinks.

a = A()
print a.f()
A.f = new_f
print a.f()

I apologize in advance if the formatting comes out wrong.

I’m surprised that C# added this as a language feature. There are reasons that string is a sealed class; preventing monkeypatching is one of them, or so I am given to understand.

Well, OK, that’s one of the reason’s it’s final in Java. I don’t do much work in C#.

no monkeypatching in Python - Alisic

import builtin
builtin.len = lambda x: 9

then do len(0)

class Spam(object): pass

def speak(self): print spam, spam, spam, spam!

Spam.speak = speak

Spam().speak()
spam, spam, spam, spam!

I have enough trouble debugging my own crappy code without trying to debug someone elses if they’ve changed some of the fundamentals of the language!

Sounds to me like its the kinda thing you’d strictly control if it was something else. like a drivers license. or license to kill :p.

In fact, I might apply for my monkeypatching license right now so I too can completely screw with other dev’s minds.

Doesn’t C++ already provide this via overloading? As Jeff always says, it’s a people problem not a compiler problem.

I do not fullt agree with your post, monkey patching is not as bad as you put it. If only we could control the scope of patch, it is no worse than any other coding idiom.

C# does a nice job controlling the scope: you must import the extension method to use it! This give the programmer complete control over the lexical (ie textual) scope of the language. I can add my String.Left, you can add your String.Left, both with different semantics and nothing fails.

Ruby and the like to not allow to control the scope, any patch applies to any code. If I patch something, it applies to all code … this is the path that leads to the gates of madness! I agree on that. Alas, none of the well known scripting language does allow such scoping. Even research does, to my best knowledge, go into the wrong direction. There are a lot of people thinking about dynamically scoped extensions, rather than using lexical scope. Dynamic scope is even worse than no scope at all!

So I am still looking forward to the language with lexical-scoped monkeypatching …