|« December 2013|
I particularly like the way he debunks the "you can build new idioms in any language" argument: different languages have different idioms for building new idioms, and that makes a difference.
The first time I delivered my "Metaprogramming Ruby" talk at OSCON this year, I was privileged to have two of the masters of Ruby metaprogramming in the audience: Rich Kilmer and David Heinemeier Hansson. Rails is, of course, the poster child for the benefits of Ruby’s metaprogramming power at the moment. But Rich paved the way with several less well known projects that showed just how much metaprogramming power Ruby has.
Anyway, during the talk I presented two approaches to doing metaprogramming, and since Rich and David were there I put them on the spot and asked them to confirm my suspicions — and I was right. The two of them approach the task in different ways.
Rich typically starts with a domain he understands fairly well, and designs domain-specific constructs to support that domain. Then he implements those constructs using Ruby. That’s the approach he used during the week of OSCON to build the prototype of a Rails interface for his ActionStep framework.
I think that’s how most people think metaprogramming is done, and it sounds really intimidating and difficult — especially when you’re not used to thinking about domain-specific languages, or you don’t understand your domain very well yet, or if you’re not familiar with the techniques of metaprogramming.
But there’s another approach, and it may surprise people that DHH used this different approach to design and build Rails. He admitted that when he started building Rails he didn’t have a deep understanding of what a web framework should look like, and he wasn’t an experienced Ruby developer. But he started with a strong desire to build good, clean code, and a devotion to the DRY principle as one way of keeping his code and design clean. And then he "explored" his way toward Rails’ metaprogramming sweetness. During programming, when he found himself writing duplicate code, or code that felt ugly or unnecessarily complex, he would look for ways to eliminate the duplication or make the code simpler and more expressive. Sometimes that was possible in ways that would seem perfectly natural to a Java programmer. But in other cases he had to go farther, augmenting the Ruby language itself through metaprogramming. In less dynamic languages, some of that duplication or ugliness would’ve remained, simply because there would be no effective way to eliminate it. (Don’t believe me? Look at the source to java.util.Arrays.sort.) But in Ruby your refactoring toolkit is bigger, and most of Ruby’s metaprogramming idioms are quite easy to use once you learn them.
That’s how I like to explain metaprogramming: as an additional set of tools that dynamic languages provide to help you eliminate bad-smelling code. Those rich idioms give you a lot of power for keeping your systems clean and simple.