Ah, the Open-Closed Principle. In static languages like C++ and Java, classes by default are Closed-Closed. In dynamic languages like JavaScript and Ruby, they are Open-Open. In Java you have to add design pattern ceremony in order to open for classes for extension; in Ruby you have to exercise discipline in order to keep them closed for modification. Yesterday Pat Maddox and I spent 80 minutes kicking the can around talking about Monkeypatching versus the Open-Closed Principle. Along the way, we talked about everything from Rebecca Black to RSpec, from Cognitive Load to watching my cat try to claw open my office window.
We’re Starting a Podcast!
Pat and I are gonna start doing this regularly. And we need a cool name for our podcast! Help us out! The giver of the winning suggestion will get something cool. Not sure what yet, but I promise it will be something cool.
But for now, just watch the rest of this post’s space for the video. Because I’m embedding it in 3… 2…
Monkeypatching and the Open-Closed Principle from David Brady on Vimeo.

I vote for “Chump don’t want no help, chump don’t get no help!”
gem talk
I would love to see the code for Fixnum#to_proc
https://github.com/dbrady/scrapbin/blob/master/stupid/fixnum_to_proc.rb
I’d say “enjoy” but I’d really prefer if you were horrified instead.
I sat for a while, stared. Then I pulled up the terminal & irb to type it in. Looked at the results.
Then a smile played on the corner of my mouth. I could no longer given in. This was ridiculous.
:lol:
Hi,
How about codechat, codrss, devtalk, devdevdev, dev++ …
Any plans for an mp3/rss feed? I prefer to listen on the move :)
Thanks, Chris.
Yep! We’re still kind of figuring out which end is up and stuff, but we have plans for direct podcast RSS as well as iTunes.
I liked your chat, hence i’m making a n00by article on ruby freezing.
This is the tutorial code i’m writing.
Do you know if there’s a base class one can inherit from in order to reject modifications, that can also be switched on and of?
There isn’t. What’s worse, remember that you can duplicate a class, and the duplicate is NOT frozen, so you can unfreeze a class as easily as:
Defrosted = Freeza.dupOr worse, you could just thaw Freeza directly:
Freeza = Freeza.dupThe first half of the lesson here is “freeze” is kind of useless in Ruby. It’s not broken, but it’s so easy to circumvent that it’s almost pointless. The second half of the lesson is that freezing classes in Ruby is anathematic, sort of the opposite of idiomatic. There are all sorts of Ruby design patterns and workflows designed to keep you safe while working with unfrozen, reopenable classes.
So, yeah. Don’t use freeze. But not because it’s broken. Freeze isn’t broken–it’s just wrong. :-)
I think you’re missing the point of the O/CP: “…closed to modification” does not mean you put an electric fence around it to keep people out. Getting to open/closed means working to create a class that is generally not _wanting_ for modifications internally, with appropriate means to extend/append behavior externally.
Note that this way of looking at it makes O/C a very context sensitive judgement. Thus the “open/closed-ness” of a class naturally changes over time, as the problem domain evolves, even if the code never changes. And it becomes entirely appropriate to make modifications, especially modifications that open a newly needed extension mechanism. Most of the times that an established class is modified to add more behavior to it, on the other hand, look like violations of the SRP to me.
The strength of Ruby around this problem is monkeypatching: the “open” part of open/closed is basically free as a language feature, rather than design work. It also seems like the weakness. As you said, it’s like putting a laser into someone’s brain. There is like plenty going on there that you don’t understand, and mistakes here are not without consequence. If on the other hand, a specific effort was made to create extension points, then you are just using a feature of the object, rather than molesting it.
I’ve been pacing around the O/CP lately, and this may sound like a non-answer, but while I haven’t changed my original opinion I also sort of agree with you. Not sure how to explain it… the ideas themselves, at their core, are not in direct opposition, but both of them have trivial implications that are mutually exclusive.
This requires more thought, methinks, but in short, I think if you’re trying to write a globally universal class you’re probably going to get it wrong, whereas if you’re designing a specialized class for a specific application you have a very good chance of getting it right. Where the gears start to strip for me is when our specialized app needs a general class and wants to specialize it. Monkeypatching, inheritance, composition… we know it can certainly be done. The hard part is doing it elegantly and appropriately.
Thanks for the comment!
Fixnum# to_proc awesome.