プログラミング言語Rubyが注目を集めています。Ruby関連の書籍が次々と出版され,2006年6月には国内初の大規模Rubyイベントである「日本Rubyカンファレンス2006」が催されました。また,Rubyで書かれたWebアプリケーション・フレームワークRuby on Rails(以下Rails)が話題となり,Rubyの高い生産性が一般に知られるようになってきました。

 Rubyの生産性はJavaの10倍とさえいわれます。なぜRubyは生産性が高いのでしょうか。それは,Rubyはいろいろな言語から優れた所を集めた「いいとこ取り」言語だからです。Rubyの特徴は「構文が強力なので,迅速な開発ができる」「人に優しい言語なので,楽しくプログラミングできる*1」「問題が起こりにくいように設計されているので,初心者でも簡単に安全に作業でき,熟練者は高度なプログラミングを行える」といった点です

 これらの特徴をシステム開発の観点から見ると,

・迅速に開発できるので,市場の変化に的確に対応できる
・開発が楽しいので,開発者の士気が向上する
・初心者にも熟練者にも向いているので,チーム開発での分業が容易になる

ということになります。

「穴埋め式」のプログラミングを実現

 Rubyは,Perlから受け継いだ正規表現によるテキスト処理機能,純粋なオブジェクト指向*2といった様々な優れた言語的特徴を持っています。加えて,Rubyは「穴埋め式プログラミング」が可能である点がシステム開発では大きなメリットになります。

 プログラムの中には実装が難しい部分もあれば易しい部分もあります。問題は,プログラムを難易度別にうまく切り分けるのが難しいことです。Rubyを使えば,難しいアルゴリズムやテクニックの部分だけを切り出して熟練プログラマが実装し,残りの易しい部分を他の人が穴埋め式に実装するといったように開発を分担できるようになります。これを可能にするのがRubyの「メタプログラミング」と「ブロック構文」という二つの機能です(図1)。

図1●Rubyのメタプログラミングとブロック構文を使えば,実装が易しい部分と難しい部分を切り分けられる
図1●Rubyのメタプログラミングとブロック構文を使えば,実装が易しい部分と難しい部分を切り分けられる

メタプログラミング
簡潔な表記で単純作業を減らす

 普通のプログラミングが“データを操作する”のに対して,“プログラムを操作する”ようなプログラミングをメタプログラミングといいます。Rubyでメタプログラミングを活用することで,プログラマの負荷を減らせます。

 メタプログラミングを使うと,「似ているけれども微妙に違う」コードのひな型を作って1個所で管理できます。これにより,難しいコードのひな型を熟練プログラマが実装し,それを基にして具体的なコードを作り出すプログラミングを他の人が担当するといった分業が可能になります。

 メタプログラミングが効果的なのは,似たような構造のプログラムをたくさん書かなければならない場合です。メタプログラミングにより,「プログラムを操作して特定のコード群を作るためのひな型」を一度作ってしまえば,あとはひな型を適用するだけでいくらでもコード群を作成できます。変更するときも,ひな型だけを変更すればよいのです。

 Rubyではクラスも単なるオブジェクトの一種なので,Classオブジェクトを操作するプログラムを書けば,それだけでメタプログラミングが可能になります。

 よく使われるメタプログラミングの機能としては「attr_reader」や「attr_accessor」があります。Javaで開発しているとき,リスト1のようにデータにアクセスするためのgetterやsetterをいちいち書くのにうんざりしたことはないでしょうか。Rubyでは,オブジェクトのプロパティを取得/設定するメソッドを,リスト2上のように簡単に記述できます。ここでは,クラスFooに,インスタンス変数@barに対するgetter/setterと,インスタンス変数@bazに対するgetterを定義しています。これらのgetterメソッドやsetterメソッドは,リスト2下のように普通に使えます。

public class Foo {
private int bar;
private String baz;
public int getBar() {
return bar;
}
public void setBar(int value) {
bar = value;
}
public String getBaz() {
return baz;
}
}
リスト1●Javaでgetterやsetterを記述する例

class Foo            # クラスFooを定義
  attr_accessor :bar # プロパティbarを定義
attr_reader :baz # プロパティbazを定義
end
foo = Foo.new # Fooオブジェクトを作成
foo.bar = 23 # プロパティbarに値を設定
puts foo.baz # プロパティbazから値を取得して出力
foo.baz = 42 # エラー。bazにはsetterが定義され
# ていない
リスト2●Rubyではgetterやsetterを簡単に記述できる

 attr_readerやattr_accessorは,何か特別な「プロパティ定義構文」のようなものではありません。Classオブジェクトが持つただのメソッドです。単に,Rubyプログラムを操作してgetterやsetterの定義を自動的に行うメソッドに過ぎません。ですから,このようなメソッドを自分で作ることもできます。Railsでは,メタプログラミングによってこの種の便利なメソッドを随所で提供し,Webアプリケーションの定型パターンをいちいち実装せずに済むようになっています。これが最近のRailsの人気の秘密でもあります。

 少しでも似たようなコードの反復があるならばメタプログラミングによって実装や保守の手間を軽減できます。Javaにおけるgetterやsetterの作成のように,似ているが少しだけ違うコードを繰り返し書かなくてはならないのは面倒です。getter/setterのようにあまり変化する余地のないものであればまだよいですが,仕様に応じて変更の必要が出てきた場合,その変更をコードに漏れなく反映するのは大変です。プログラムを操作するプログラムを使って似たようなコードを自動的に生成するようにしておけば,変更が生じた場合でも基の部分(ひな型)だけを書き換えればよいので,保守性が向上します。

 Javaでのメタプログラミングは,リフレクションAPIやバイトコード操作*3を用い,ときにはJava仮想マシン(Java VM)の仕様の知識まで要求される難易度の高いものです。これに対し,Rubyでは新規にクラスを作成するClass.newやメソッドを定義するdefine_methodのようにプログラム自体を操作するメソッドが豊富に用意されています。いくらかRubyに習熟すれば,誰でも容易にメタプログラミングの恩恵にあずかることができるのです。