Ideas on "Why Living Dangerous can be A Good Thing" in Ruby?

Indispensable uses of Ruby meta-programing.

  1. Module.attr and friends are probably the simplest (and strongest)
    uses that highlight the advantages of meta-programming.

  2. Rails’ ActiveRecord.

  3. Dwemthy’s Creature class. http://poignantguide.net/dwemthy/

When boiled down, Dwemthy’s Creature class creates a domain-specific
mini-language that is actual Ruby code.

I’m pretty sure someone else brought up domain-specific languages in
this thread, but here are some links to learn more about them.

http://en.wikipedia.org/wiki/Domain-
specific_language#Advantages_and_Disadvantages_of_DSLs

DSL’s are used everywhere: in Sendmail configuration files, Windows
resource files, World of Warcraft UI scripting, etc. One obvious
advantage of embedded mini-languages, like sub-classes of Creature,
over external ones, like configuration files, is the ability to apply
Ruby’s tools, like the irb, directly on the language.

~ ryan ~

On 1/9/06, Todd [email protected] wrote:

At least, that was my first impression. That, until I started seeing
how impressive not only the coding practices were, but also the
incredible knowledge base in the Ruby community. Not to mention how
it has made my life a bit easier.

I’d like to quote this snippet as the beginning of my article, is that
okay?

This brings up an interesting point though. In Ruby, idioms are more
than just ‘good practice’. They really do matter, because they are
our biggest sense of ‘security’. This of course leaves the
responsibilities in the hands of the coders, but from my experience,
the majority of the well known applications adhere to good style, and
their developers are consistant at being idiomatic in their
application design. The same can not necessarily be said for the
majority in other languages.

From: “Todd” [email protected]
Newsgroups: comp.lang.ruby
Subject: Re: Ideas on “Why Living Dangerous can be A Good Thing” in
Ruby?
Date: Sun, 08 Jan 2006 13:16:52 -0800

James Edward G. II wrote:

On Jan 8, 2006, at 2:21 PM, Gregory B. wrote:

How would you (the community) define meta-programming

Code that writes code.

A shiver goes up my spine :slight_smile:

open class system

Classes that can be changed (methods added, removed, etc.) at runtime.

Scary.

and the dynamic nature of ruby?

That’s a lot harder. :slight_smile:

I like to think that Ruby does away with much of the compile time vs
runtime separation and that is a big source of it’s dynamic nature.

You will need a better definition than that though, of course… :wink:

James Edward G. II

The programmer in me loves Ruby for it’s relative simplicity (coupled
with relative complexity if need be). The IT and DBA in me shudders at
the thought that such a thing exists, simply because data integrity
should be paramount! More important than your family, for God’s sake!
It has to be something you can put your foot on and be sure it won’t
move.

I mean, here you have a black box that a few moments from now may not
be a black box anymore! It may turn green… It may pop out at you
like those fond memories of the jack-in-the-box. You look at it, prod
it, it isn’t reliable (you posit), it doesn’t come up like the sun in
the morning every day, and start to feel there’s some deep and dark
sinister purpose waiting to be unleashed. This program, this thing,
suddenly feels like almost sort of a Pandora’s box. In that moment of
inspiration, you quickly walk away feeling better about yourself for
suggesting another, more ‘stable’, language that you can use. The CIO
will be proud :slight_smile:

At least, that was my first impression. That, until I started seeing
how impressive not only the coding practices were, but also the
incredible knowledge base in the Ruby community. Not to mention how
it has made my life a bit easier.

It is rather simple to program malicious code in Ruby, but that may be
quite
possible in any programming medium.

Todd

On Sun, 2006-01-08 at 23:47, Steve L. wrote:

If someone can show me an advantage to adding methods and instance variables
in real time, and that advantage can’t be realized with normal OOP
techniques, I’ll keep an open mind. But unless it offers me a unique benefit
that I need, I wouldn’t do it.

I recently wrote some code where I had to retrieve an attribute from a
REXML attribute list based on its name and namespace. The REXML
attribute list does have a method for retrieving attributes based on
namespace prefix and name, but this is not very useful. A namespace
aware XML processor, such as an XSLT processor, can, without breaking
any rules, change prefixes at will.

I couldn’t just subclass the attribute list, because the REXML parser
would not use my subclass when building a node tree from an XML
document. However, I could do this:

module REXML
class Attributes
def get_attribute_ns(namespace, name)
each_attribute() { |attribute|
if name == attribute.name &&
namespace == attribute.namespace()
return attribute
end
}
nil
end
end
end

Which enabled me to write code like this:

actual_attribute =
actual_attributes.get_attribute_ns(expected_namespace, expected_name)

I could have solved the problem with an external helper class instead,
but that would, in my opinion, have been a clumsier solution.

/Henrik

http://www.henrikmartensson.org/ - Reflections on software development

James Edward G. II wrote:

On Jan 8, 2006, at 2:21 PM, Gregory B. wrote:

How would you (the community) define meta-programming

Code that writes code.

A shiver goes up my spine :slight_smile:

open class system

Classes that can be changed (methods added, removed, etc.) at runtime.

Scary.

and the dynamic nature of ruby?

That’s a lot harder. :slight_smile:

I like to think that Ruby does away with much of the compile time vs
runtime separation and that is a big source of it’s dynamic nature.

You will need a better definition than that though, of course… :wink:

James Edward G. II

The programmer in me loves Ruby for it’s relative simplicity (coupled
with relative complexity if need be). The IT and DBA in me shudders at
the thought that such a thing exists, simply because data integrity
should be paramount; more important than your family, for God’s sake!
It has to be something you can put your foot on and be sure it won’t
move.

I mean, here you have a black box that a few moments from now may not
be a black box anymore! It may turn green… It may pop out at you
like those fond memories of the jack-in-the-box. You look at it, prod
it, it isn’t reliable (you posit), it doesn’t come up like the sun in
the morning every day, and start to feel there’s some deep and dark
sinister purpose waiting to be unleashed. This program, this thing,
suddenly feels like almost sort of a Pandora’s box. In that moment of
inspiration, you quickly walk away feeling better about yourself for
suggesting another, more ‘stable’, language that we can use. The CIO
will be proud :slight_smile:

At least, that was my first impression. That, until I started seeing
how impressive not only the coding practices were, but also the
incredible knowledge base in the Ruby community. Not to mention how it
has made my life a bit easier.

Todd

James Edward G. II wrote:

On Jan 8, 2006, at 2:21 PM, Gregory B. wrote:

How would you (the community) define meta-programming

Code that writes code.

A shiver goes up my spine :slight_smile:

open class system

Classes that can be changed (methods added, removed, etc.) at runtime.

Scary.

and the dynamic nature of ruby?

That’s a lot harder. :slight_smile:

I like to think that Ruby does away with much of the compile time vs
runtime separation and that is a big source of it’s dynamic nature.

You will need a better definition than that though, of course… :wink:

James Edward G. II

The programmer in me loves Ruby for it’s relative simplicity (coupled
with relative complexity if need be). The IT and DBA in me shudders at
the thought that such a thing exists, simply because data integrity
should be paramount; more important than your family, for God’s sake!
It has to be something you can put your foot on and be sure it won’t
move.

I mean, here you have a black box that a few moments from now may not
be a black box anymore! It may turn green… It may pop out at you
like those fond memories of the jack-in-the-box. You look at it, prod
it, it isn’t reliable (you posit), it doesn’t come up like the sun in
the morning every day, and start to feel there’s some deep and dark
sinister purpose waiting to be unleashed. This program, this thing,
suddenly feels like almost sort of a Pandora’s box. In that moment of
inspiration, you quickly walk away feeling better about yourself for
suggesting another, more ‘stable’, language that we can use. The CIO
will be proud :slight_smile:

At least, that was my first impression. That, until I started seeing
how impressive not only the coding practices were, but also the
incredible knowledge base in the Ruby community. Not to mention how it
has made my life a bit easier.

Todd

On 1/8/06, Gregory B. [email protected] wrote:

I mean, my general advice when it comes to ruby when asked about
security is that I basically respond, "There is none, but it’s not as
bad as you’d expect. Write proper test suites, code responsibly, and
make sure you nail down those edge cases. Continuous integration is a
must, and idiomatic code with proper style will help make the API
less likely to cause damage (such as the use of ! and other
indicators).

There’s documentation for how to do good APIs here:
http://rpa-base.rubyforge.org/wiki/wiki.cgi?GoodAPIDesign

I hope that’s useful; feel free to edit and add/change/add discussion.

However, to the outsider, this is only an explanation of “how” to
overcome the apparent “flaw”. I’d like to do as good a job I can of
explaining why it isn’t a flaw, when practiced correctly.

Let’s look at it as a cost/benefit analysis. The cost of declaring
variables and types end up as roughly half the code size. That’s
twice the amount to write, and, more importantly twice the amount to
read, twice the amount of places to change when refactoring, etc. It
also means that there’s a lot of things we can’t do, because we are
“protected” from it.

At this cost, the type and variable declarations had better give us a
lot. In practice, I find that they give me very little, bug wise:
Maybe 5% of my simplest bugs are detected by them. The advantages I
get are in the speed of the compiled code, and as documentation.
However, these benefits are too small to be worthwhile for the size
projects I presently do (one and two person projects).

I’ve implemented a system for doing run time checks of type
declarations, it’s available from RPA (as types) and from
Index of /~eivind/ruby/types/ This allows very
flexible type checks for Ruby programs, adding whatever amount of type
discipline you want. In practice, I found this to just get in the way

  • it detected very few bugs, and added more stuff to change when I did
    refactoring.

Eivind.

Hi –

On Mon, 9 Jan 2006, Steve L. wrote:

That code gets executed, and then there’s a class called C with an

that.
I think you mean method_missing. It has nothing to do with instance
variables; it’s just a hook or callback that you can define to
intercept calls to non-existent methods. What you do at that point is
up to you. You can also just not define it, in which case a call to a
non-existent message will raise an exception.

There’s nothing inherently dangerous or non-deterministic about
method_missing. It’s basically a control-flow technique.

David


David A. Black
[email protected]

“Ruby for Rails”, from Manning Publications, coming April 2006!

Hi –

On Mon, 9 Jan 2006, Gregory B. wrote:

That’s the million dollar question we’ve yet to answer :slight_smile:
It’s not that central a question to me. In my own work with Ruby, I
can go from one month to the next without ever thinking about what
metaprogramming is, or whether or not I’m doing anything that people
would put in that category – whereas thinking about the dynamic
nature of Ruby I’ve always found not only interesting but
enlightening.

I definitely don’t think that metaprogramming is an extreme or higher
form of dynamism. It’s just a meta form of programming :slight_smile:

David


David A. Black
[email protected]

“Ruby for Rails”, from Manning Publications, coming April 2006!

Gregory B. wrote:

[snippet]

I’d like to quote this snippet as the beginning of my article, is that okay?

Sure, whatever you think is best for your article.

This brings up an interesting point though. In Ruby, idioms are more
than just ‘good practice’. They really do matter, because they are
our biggest sense of ‘security’. This of course leaves the
responsibilities in the hands of the coders, but from my experience,
the majority of the well known applications adhere to good style, and
their developers are consistant at being idiomatic in their
application design. The same can not necessarily be said for the
majority in other languages.

Well said.

OT, why did my original post show up on this group three times? I seem
to be having an issue with 3 lately. Hmmmm…

Todd

Hi –

On Mon, 9 Jan 2006, Gregory B. wrote:

This brings up an interesting point though. In Ruby, idioms are more
than just ‘good practice’. They really do matter, because they are
our biggest sense of ‘security’. This of course leaves the
responsibilities in the hands of the coders, but from my experience,
the majority of the well known applications adhere to good style, and
their developers are consistant at being idiomatic in their
application design. The same can not necessarily be said for the
majority in other languages.

I agree – really “Ruby” in the sense we’re talking about is more than
just the language; it’s also the coding practices, and the fact that
there are ways (including, but not limited to, discussion with other
Rubyists) of making good decisions about what to do.

I have to say, I’m quite surprised that the image of Ruby that’s
emerging in this thread is, at least in large part, of a sort of
mine-field that we all have to tiptoe our way through – as if the
language is a malevolent force that we write programs in spite of, and
in triumph over, rather than in harmony with. I’ve never perceived it
that way, and I wish I could find the words to turn the tide for
others.

I guess it comes down to this: worrying that something like dynamic
method redefinition is going to “bite” you, or “shoot you in the
foot”, or whatever, at random times, without warning, is a bit like
worrying that your C program is going to erase all the files on your
hard drive. If you don’t want it to, don’t tell it to, and it won’t.

Most of the real issues in this realm have to do with modifying core
classes. The main reason not to do this is that if someone else uses
your code as part of a program, your changes will affect their code
too. Under circumstances where that can’t happen, there’s no reason
not to.

Meanwhile, other dynamic-programming things – like defining
method_missing, creating classes batch-wise, whatever – are cut from
exactly the same cloth as the Ruby that interprets your script in the
first place. They’re an opportunity to think expansively about what
you can do.

David


David A. Black
[email protected]

“Ruby for Rails”, from Manning Publications, coming April 2006!

On Monday 09 January 2006 08:26 am, [email protected] wrote:

I guess it comes down to this: worrying that something like dynamic
method redefinition is going to “bite” you, or “shoot you in the
foot”, or whatever, at random times, without warning, is a bit like
worrying that your C program is going to erase all the files on your
hard drive. If you don’t want it to, don’t tell it to, and it won’t.

To get Ruby to do bad stuff, you need to enunciate quite clearly that
you want
it to do something bad. To get C to do something bad, a muffled mumble
could
be interpreted (compiled :slight_smile: by C to do something bad.

Nobody’s infallable. C is much more unforgiving of programmer error than
Ruby.

SteveT

Steve L.

[email protected]

Todd wrote:

Gregory B. wrote:

[snippet]

I’d like to quote this snippet as the beginning of my article, is that okay?

BTW, I should mention that using a quote like that may – to your
intented audience – sound a bit pretentious as the start of an
article. You need a lead-in for something like that. Well, you need
most everything that came beforehand in this thread, or at least a
summary of it.

Todd

Eivind E. wrote:

http://rpa-base.rubyforge.org/wiki/wiki.cgi?GoodAPIDesign
read, twice the amount of places to change when refactoring, etc. It
also means that there’s a lot of things we can’t do, because we are
“protected” from it.

At this cost, the type and variable declarations had better give us a
lot. In practice, I find that they give me very little, bug wise:
Maybe 5% of my simplest bugs are detected by them. The advantages I
get are in the speed of the compiled code, and as documentation.
However, these benefits are too small to be worthwhile for the size
projects I presently do (one and two person projects).

Does a language with type-inference require as many type and variable
declarations as a language without type-inference?

Is the C++ type system the same as the SML type system?

Will programmers who passively suffer compiler type-checking detect as
many bugs as programmers who actively use ‘type-full’ programming as a
checking-tool?

On 1/9/06, Todd [email protected] wrote:

BTW, I should mention that using a quote like that may – to your
intented audience – sound a bit pretentious as the start of an
article. You need a lead-in for something like that. Well, you need
most everything that came beforehand in this thread, or at least a
summary of it.

I plan to go in reverse of that :wink: I want it to sound pretentious,
because your observation is the common one you hear from someone who
hasn’t done much ruby or seen it actively working. I’m not sure if
I’m going to use it at this point, but I thought it was a good example
of the common concerns.

On 1/9/06, [email protected] [email protected] wrote:

would put in that category – whereas thinking about the dynamic
nature of Ruby I’ve always found not only interesting but
enlightening.

Same here. My concern is with the fear it seems to cause in people
migrating from the static world. I honestly am very lazy and simply
do not want to argue the static vs. dynamic typing, early binding vs
open class structure, compile vs. runtime arguments anymore. So, I’m
trying to write a well formed article I can point people to :wink:

I definitely don’t think that metaprogramming is an extreme or higher
form of dynamism. It’s just a meta form of programming :slight_smile:

well said.

On Jan 9, 2006, at 1:55 PM, Gregory B. wrote:

My concern is with the fear it seems to cause in people
migrating from the static world.

What is being feared? I’m still not entirely
sure I understand what specific concerns lead to insecurity
about using a dynamic language like Ruby. I’ll bet if you
did some search of the literature you might find some
useful history on this debate as it relates to Smalltalk
and/or CLOS.

I’m not saying there aren’t valid concerns. What I’m saying
is: can those concerns be elaborated beyond some general
notion of ‘fear’ or ‘security’ and wouldn’t that help construct
a more appropriate response?

Gary W.

On 1/9/06, [email protected] [email protected] wrote:

I have to say, I’m quite surprised that the image of Ruby that’s
emerging in this thread is, at least in large part, of a sort of
mine-field that we all have to tiptoe our way through – as if the
language is a malevolent force that we write programs in spite of, and
in triumph over, rather than in harmony with. I’ve never perceived it
that way, and I wish I could find the words to turn the tide for
others.

David, if it wasn’t fully clear, I was being somewhat facetious when I
was talking about “Living Dangerous”. However, I think I will use the
title “The Open Nature of Ruby” because it sounds a lot more positive
and friendly.

You make a wonderful point. I doubt very many people who are doing
ruby actively day to day think “Oh my god… what havoc is this code
going to unleash”. In fact, from my experience, Ruby has seemed to
comfort me and give me confidence more than most any other language.

On 1/9/06, [email protected] [email protected] wrote:

and/or CLOS.
If you remember from our first New Haven Rubyists meeting, there was a
decent amount of tension from the Java guys in the house. People who
tend to lean on the compiler for support feel like they’re going to
fall flatfaced upon entering Ruby. We know that this isn’t true, but
I am not entirely sure how to address it, though this thread has given
me some ideas.

On 1/9/06, [email protected] [email protected] wrote:

I’m not saying there aren’t valid concerns. What I’m saying
is: can those concerns be elaborated beyond some general
notion of ‘fear’ or ‘security’ and wouldn’t that help construct
a more appropriate response?

The fear in part has to do with type checking. Ruby being typeless
scares people who tend to believe that type checking is absolutely
essential to ‘safe’ programming. But as David Black and many others
had mentioned, safety is in the hands of the programmer.

I personally have never crashed my computer using Ruby. On the
gripping hand, I’ve done many unsavory things in C, and at least a
couple in Perl. These were ‘accidents’.

I think that it’s worthwhile to point that since low-level management
is not something we need to do in Ruby, such accidents are far less
likely to happen. I think that this type of thing makes up the
lionshare of bugs and vulnerabilities. You hear about overflow
exploits on a day to day basis… you very rarely hear of the l33t
h4x0r using metaprogramming to destroy a system.

People are afraid that without the type checking safety net, that the
program will begin to act unpredictable or will be capable of doing
random unsavory things.

The bottom line is, if you’re in a production environment, you should
have all of your projects running against a comprehensive test suite.
Continuous integration should be assumed. Though it’s universally
agreeable that regardless of the language you choose, you ‘should’ be
doing this, I do believe the popular opinion in most of the
experienced ruby core community is that you MUST be doing this.

And you know what? It takes me about 30 seconds to find out what
jimmy’s evil little gem has done to my system when I run my units on
all my projects to make sure they haven’t broken with the addition of
a new library.

I mean, come on, does anyone add a require ‘foo’ from the wild into
production code WITHOUT running their units? If they do, well then
all bets are off.

The biggest thing that those with a fear of dynamicity need to
recognize is that it’s not as if we’re programming in Java or C++ but
just removing the type checking and other ‘security’ measures. We’re
programming in a language that was designed from the ground up to be
used in the way we’re using it.

Reflection and introspection in Ruby are so good we can actually use
it to PREVENT unsavory effects through using it in our unit tests.
Things like method_missing and respond_to? and the ability to search
our entire object space are features, not bugs.

This type of design allows for things like inversion of control /
dependency injection, which can be used to cleanly tack on logging and
unit testing features WITHOUT having to pollute methods with secondary
code.

I think that things like automated memoization make me LESS likely to
screw up than it would to roll my own in every single method that
needs it.

Ruby is no different than any other language. Bad code and bad coders
will cause problems, good code and good coders will solve problems.
Simply because it was not a design goal to make the programmer feel
safe and ‘secure’, but rather to make them feel powerful is NOT a
flaw.

Wow… i’m ranting here. Better here than in my article I suppose,
but there are my answers to our still yet to be precisely defined
questions :wink:

Let me know what you think.
-Greg