Red Squirrel Reflections
Dave Hoover explores the psychology of software development

Dave Hoover
dave.hoover@gmail.com

Categories
All [Atom]
Craftsmanship [Atom]
Dynamic [Atom]
Intersection [Atom]
Learning [Atom]
Links [Atom]
Polyglot [Atom]
Projects [Atom]
XP [Atom]
Old Blog

Obtivian Blogs

Andy Maleh
Colin Harris
Fred Polgardy
Jim Breen
Kevin Taylor
Todd Webb
Turner King
Tyler Jennings

Archives

March 2009 (1)
January 2009 (1)
December 2008 (1)
October 2008 (3)
September 2008 (1)
June 2008 (4)
April 2008 (3)
March 2008 (1)
February 2008 (1)
August 2007 (1)
July 2007 (1)
June 2007 (1)
May 2007 (4)
April 2007 (3)
March 2007 (5)
February 2007 (6)
January 2007 (6)
December 2006 (10)
November 2006 (5)
October 2006 (8)
September 2006 (8)
August 2006 (5)
July 2006 (12)
June 2006 (7)
May 2006 (5)
April 2006 (5)
March 2006 (4)
February 2006 (2)
January 2006 (5)
December 2005 (5)
November 2005 (3)
October 2005 (3)
September 2005 (6)
August 2005 (4)
July 2005 (7)
June 2005 (14)
May 2005 (6)
April 2005 (8)
March 2005 (9)
February 2005 (11)
January 2005 (16)
Old Archives

 

Sat, 15 Jul 2006

def_init'ly DRYer Ruby

I'm leading a study group at my current client. Nine of us are reading Ruby for Rails and get together every week with a projector to answer questions and hack away at some examples. I read a few chapters ahead so that I can provide exercises for the group to prepare for our meetings. I was reading chapter 5 today, it's fairly basic Ruby stuff, introducing the convenient and self-documenting attr_* methods. The following class is the example from the book, your typical brainless data holder...
class Ticket
  def initialize(venue, date)
    @venue = venue
    @date = date
  end

  def price=(price)
    @price = price
  end

  def venue
    @venue
  end

  def date
    @date
  end

  def price
    @price
  end
end
Using the attr_* methods, the mind-numbingly boring getters and setters can be collapsed into this more readable version...
class Ticket
  attr_reader :venue, :date, :price
  attr_writer :price

  def initialize(venue, date)
    @venue = venue
    @date = date
  end
end
Now, I've written constructors like that one more times than I care to remember in all sorts of languages. And everytime I do it, I feel a twinge of pain, it just feels silly to have to do that mapping of parameters to instance variables manually. When I'm writing Java, IDEA reduces this pain by generating most of it after a few ALT-ENTERs. But when I'm writing Ruby, repetitive constructs like these hurt even more, since that sort of repetition goes against one of the Ruby culture's most fundamental values: DRYness.

And thus the cousin to the attr_* siblings was born: def_init. By using def_init, the constuctor in the example could be reduced to...

class Ticket
  attr_reader :venue, :date, :price
  attr_writer :price
  def_init :venue, :date
end
I'm guessing that this functionality is already out there somewhere, so let me know if I've missed it. Here's the code that makes it happen...
class Class
  def def_init(*attrs)
    constructor = "def initialize("
    constructor << attrs.map{|a| a.to_s}.join(",")
    constructor << ")\n"
    attrs.each do |attribute|
      constructor << "@#{attribute} = #{attribute}\n"
    end
    constructor << "end"
    class_eval(constructor)
  end
end
It's interesting to note how Ruby and Java solve these sort of repetition problems differently. Java tends to solve repetition with excellent tools that generate code at development time, while Ruby tends to solve it through giving developers the power to generate code at runtime.

[/dynamic] permanent link


powered by blosxom