I often feel, when reading articles like this about programming, that they would be significantly enhanced by telling me why I should care about metaprogramming.

It is not obvious to me that there is any value in being able to declare a method on an object via metaprogramming versus just writing the method into the class. If you, like me, have to see obvious value to change your programming practices, let me provide you with a bit of motivation:

Metaprogramming allows you to cut down on boilerplate code, making your programs shorter, easier to write, easier to read, and easier to test. Also, it reduces the impact of changes.

For example, metaprogramming is used internally to provide a lot of the "magic" that people associate with Rails. You never have to define a find_by_email method in ActiveRecord because just putting an email column on the table causes that method to be automatically generated for you. That saves you perhaps three lines of code in the instant case, but when you start to compound that over several dozen columns on 10 different tables, you're talking about hundreds of lines of negacode.

Yeah, great for library writers, right? How do you use this in actual application code? Well, to pick one example from my application: a stupendous portion of the "business logic" involved in my app is creating print jobs. Print jobs have a grab bag of properties associated with them and, every time I implement a new feature, that means they typically get another property (or several). If I had implemented that via adding a new column every time I added a new feature, I'd have to add a new column to my table every week, and it would get progressively harder and harder to manage.

Instead, I have a column called options in the table which is just a JSON grab bag. My model class has a hash called default options, which has a bunch of keys representing virtual properties and a bunch of values for what they should take if the user hasn't specified anything. A quick little metaprogramming loop goes over the default options hash and adds getters and setters for those properties, so that they work transparently from the object. (For example, print_job.name = "foo" sets print_job[:options][:name] = "foo".) Another line of code sets the default values at initialization time.

This means that adding another property to my print jobs requires adding one entry to that hash, rather than writing a bunch of getters, setters, and dealing with migrating the 100,000 print jobs in the database which don't have a value for it yet. This is extraordinarily powerful in reducing the impact of changes.

For example, I recently added color support to my application. This required adding five properties to my print jobs. I just checked in SVN for how much of an impact this had on the printing class -- nine lines. The 35 lines of boilerplate getters/setters I didn't have to add contained exactly no typos, required no test cases, and caused no bugs. The data migration I didn't write caused no downtime. The special cases that don't exist for jobs without color information caused no subtle bugs two weeks later when they fell out of the cache and then got regenerated.

[Edited to add: It occurs to me that I have a contrasting example, too. I do Big Freaking Java Enterprise Web Apps at the day job.

Recently, we had to add the JSON grab bag approach to our internal framework, because it would allow us to customize what data we associate with e.g. students on a per-university basis without requiring code changes, separate schema, and a redeployment.

This took a lot of blood, sweat, and tears from our best engineer, myself, and one contractor -- probably about 2.5 man months, total. We did it with 100% plain ol' Java, rather than metaprogramming.

It will save us literally hundreds of thousands of dollars, so that isn't a terrible tradeoff, but if I had been using Ruby, I could have done it by myself in two to three days.]