本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

境界を越える: アクティブ・レコードを探る

ラッピングの波をとらえる

Bruce Tate (bruce.tate@j2life.com), Independent Consultant, J2Life, LLC
Photo of Bruce Tate
Bruce Tate氏は、独立コンサルタント兼執筆者です。彼は12年間IBMに勤め、Javaのproof-of-conceptチームなどの様々な仕事に携わりました。Tate氏は、IBMで、Austinのあるスタートアップのためにソリューション開発組織を運営していましたが、その後IBMを退職し、J2Life, LLC という独自の事業を立ち上げました。彼は、Bitter Javaを含め、Javaアンチパターンに関する3冊の書籍を執筆しました。彼の連絡先は、bruce.tate@j2life.comです。

概要: Java™プログラミング言語は、ベンダーや顧客、業界全体全体に渡って大成功を収めています。しかし、どんな用途にも最適、というようなプログラミング言語はありません。この、Bruce Tateによる新しいシリーズでは、他の言語が大きな問題をどのように解決しているか、そうした解決方法がJava開発者にとって何を意味するのかを探ります。今回は第1回目として、Ruby on Railsの背後にあるパーシスタンス・エンジンである、アクティブ・レコードについて調べます。アクティブ・レコードは、典型的なコンフィギュレーション機構から基本的なアーキテクチャー上の選択肢まで、多くのJava規則とは異なっています。その結果、過激な妥協を強調し、また過激な生産性を生むフレームワークとなっています。

このシリーズの他の記事を見る

日付:  2006年 3月 07日
レベル:  初級 この記事の原文:  英語
アクティビティー: 3267 ビュー
お気軽にご意見・ご感想をお寄せください: 


私にとって2005年は不思議な年でした。私はこの10年来初めて、Java以外の言語による本格的な開発を始めました。最初の部分を処理している間、ビジネス・パートナーと私は、素早く概念検証することには非常な成功を収めました。しかし私達は岐路に立ったのです。つまり、Java開発を続けるべきか、あるいは何か、過激で新しいものに切り換えるべきかという選択を下す必要がありました。Javaにとどまる理由としては、次のように幾つかを挙げることができます。

  • (新しい言語では)まったく初めから学ばなければならない
  • Javaのプログラミング・コミュニティーは非常に強力なため、切り換えることを顧客に納得させるのは難しい
  • (他の言語では)Javaのように何千ものオープンソース・プロジェクトから自由に選択することは不可能

このシリーズについて

この、『境界を越える』シリーズでは、著者であるBruce Tateが、「今日のJavaプログラマーは、他の手法や言語を学ぶことから多くを得ることができる」という概念を押し進めます。プログラミングの世界の様相は、あらゆる開発プロジェクトにとってJavaを選択することが明確に最善であった頃から変わってきています。他のフレームワークもJavaフレームワークと同じ構築形態をとりつつあり、また他の言語での概念を学ぶことによって、それをJavaプログラミングに生かすこともできます。皆さんが書くPython(あるいはRubyやSmalltalk、その他何であれ)コードによって、皆さんのJavaコーディングに対する取り組みも変わる可能性があるのです。

このシリーズでは、Java開発とは大幅に異なりながら、同時にJava開発に直接応用できるプログラミング概念や手法を紹介します。場合によると、こうした技術を利用するためには統合が必要かも知れません。また場合によると、ここで紹介する概念を直接応用することもできます。他の言語やフレームワークが、開発者やフレームワーク、Javaコミュニティーでの基本的な手法にまで与えうる影響に比べると、個々のツールはそれほど重要ではありません。

しかし私達は他の言語で開発を行うという考えを捨てず、Ruby言語上に構築されたWebアプリケーション・フレームワークである、Ruby on Railsでアプリケーションの構築を始めました。そして予想もしなかった成功を収めたのです。それ以来私は、うまく時間を切り分けて、Javaの指導と開発(ほとんどはHibernateとSpringに関するもの)と、Rubyの指導と開発の両方を行うようになりました。そして、時には他の手法や言語を学ぶことが非常に重要だと信ずるようになりました。その理由として、下記を挙げることができます。

  • Javaはどんな問題にも完璧な言語というわけではない
  • 新しい考え方をJavaプログラミングに反映することができる
  • 他のフレームワークもJavaフレームワークと同じ構築形態をとりつつある

こうした考え方を示すためのシリーズの第1回として、今回はRuby on Railsのパーシスタンス・アーキテクチャーの核心である、アクティブ・レコードを見て行きます。また、スキーマ・マイグレーションについても解説します。

アクティブ・レコード: 大幅に異なるもの

正直に言うと、私はRailsを最初に試した時、かなり傲慢でした。アクティブ・レコードなど丸で役に立たないと思い込んでいたのですが、実は一部の問題に対しては、あらゆるものが用意されていることを知ったのです。

アクティブ・レコードがパーシスタンスをどう処理するかを学ぶためには、少しコードを書いてみることが一番です。この例ではMySQLデータベースを使っていますが、少し変更すれば、このコードを他のデータベースにも使うことができます。

Railsを設定する

アクティブ・レコードを最も簡単に使うには、何と言ってもRuby on Railsを使うことです。この記事のコードを追うためには、Ruby on Railsをインストールする必要があります(参考文献)。

次に、プロジェクトを作成します。Railsで新しいプロジェクトを作成するためのディレクトリーに行き、下記をタイプします。

rails email_list

Railsがプロジェクトを作成すると、しゃれたRailsツールからアクティブ・レコードを使うことができます。残るステップは、データベースをコンフィギュレーションすることです。email_list_developmentというデータベースを作成し、config/database.ymlファイルを編集して、次のようにします(ユーザー名とパスワードをタイプすることを忘れないでください)。

development:
adapter: mysql
database: email_list_development
host: localhost
username: root
password:

この記事では、テスト環境や実稼働環境を気にする必要はないため、必要なコンフィギュレーションはこれだけです。これで準備完了です。


一つの例

Hibernateでは、通常は最初にJavaオブジェクトの開発から始めますが、これはHibernateが『マッピング・フレームワーク』であるためです。Hibernateの世界では、オブジェクト・モデルが中心となります。アクティブ・レコードは、『ラッピング・フレームワーク』です。そのため、まずデータベース・テーブルを作成することから始めます。アクティブ・レコードの世界では、リレーショナル・スキーマが中心なのです。データベース・テーブルを作成するためには、GUIを使用するか、あるいは下記のようなスクリプトをタイプします。

CREATE TABLE people (
  id int(11) NOT NULL auto_increment,
  first_name varchar(255),
  last_name varchar(255), 
  email varchar(255),
  PRIMARY KEY (id)
);

アクティブ・レコード・クラスを作成する

次に、app/models/person.rbというファイルを作成します。これを、次のようにします。

class Person < ActiveRecord::Base
end

このRubyコードは、ActiveRecord::Baseというスーパークラスを持つPersonというコードを作成します。(とりあえず、BaseはJavaクラスのようなものであり、ActiveRecordはJavaパッケージのようなものだと思ってください。)驚くなかれ、たったこれだけで、非常に多くのことができるのです。

これで、アクティブ・レコードのコンソール内からPersonを操作することができます。このコンソールを使うと、データベースを持つオブジェクトを、Rubyインタープリターの中から使えるのです。下記をタイプします。

ruby script/console.

今度は新しいpersonを作成します。下記のRubyコマンドをタイプします。

>> person = Person.new
>> person.first_name = "Bruce"
>> person.last_name = "Tate"
>> person.email = "bruce.tate@nospam.j2life.com"
>> person.save
>> person = Person.new
>> person.first_name = "Tom"
>> person.save

これまでアクティブ・レコードを使ったことのない人にとっては、新鮮に、そして興味深く見えるのではないでしょうか。この小さな例の中には、2つの重要な機能、つまり『コンフィギュレーションよりも規則優先(convention over configuration)』と『メタプログラミング』が含まれています。

『コンフィギュレーションよりも規則優先』では、自分が選択した名前に基づいてコンフィギュレーションを推測できるため、面倒な繰り返しを避けることができます。上記では何らマッピングをコンフィギュレーションする必要がありませんでしたが、これはデータベース・テーブルの構築をRailsの命名規則に従って行ったためです。こうした名前の主なものとしては、下記があります。

  • モデル・クラス名(EmailAccountなど)は、CamelCaseであり、英語の単数です。
  • データベース・テーブル名(email_accounts)は、単語間に下線(underscore)を使用し、英語の複数です。
  • プライマリー・キーは、リレーショナル・データベースの行を固有識別します。アクティブ・レコードは、プライマリー・キーとしてidを使用しています。
  • 外部キーは、データベース・テーブルを連結します。アクティブ・レコードは、英語の単数と_id接尾辞を持つ外部キー(person_idなど)を使用しています。

Railsの命名規則に従う場合には、『コンフィギュレーションよりも規則優先』によって一層高速にすることができますが、この命名規則をオーバーライドすることもできます。例えば、次のようなpersonが可能です。

class Person < ActiveRecord::Base
  set_primary_key "ssn"
end

ですから『コンフィギュレーションよりも規則優先』によって不必要な制限が課されることはありません。単純に、一貫した命名方式を使えば大きな見返りが得られるのです。

メタプログラミングも、アクティブ・レコードの持つ、もう1つの重要機能です。アクティブ・レコードでは、Rubyのリフレクション機能とメタプログラミング機能を多用しています。メタプログラミングというのは単純に、「プログラムを書く、あるいは変更する」プログラムを書くことです。この場合では、Baseクラスが、データベース中の全カラムに対してpersonクラスに属性を追加しています。何らコードを書いたり生成したりする必要はありませんでしたが、person.first_nameやperson.last_name、person.emailなどを使うことができています。メタプログラミングについては、この先でさらに詳しく説明します。

データを検証する

アクティブ・レコードには、Javaフレームワークに無いような機能も幾つか含まれています。例えば『モデル・ベース検証(model-based validation)』です。モデル・ベース検証を利用すると、データベース内のデータの一貫性を保証することができます。person.rbを次のように変更します。

class Person < ActiveRecord::Base
  validates_presence_of :email
end

コンソールから、(personは変更されているので)personをロードし、下記のRubyコマンドをタイプします。

>> load 'app/models/person.rb'
>> person = Person.new
>> person.save

Rubyがfalseを返します。このように、任意のRubyプロパティーに対するエラー・メッセージを見ることができます。

>> puts person.errors[:email]
can't be blank


リレーションシップをラップする

ここまではJavaフレームワークでは普通見られないような機能を見てきましたが、まだ信じていない人もいるかも知れません。実は、データベース・アプリケーションのプログラミングで最も難しいのは、リレーションシップの管理部分であることが多いものです。そうした場合にアクティブ・レコードが役立つことをお見せしましょう。addressesという、別のテーブルを作成します。

CREATE TABLE addresses (
  id int(11) NOT NULL auto_increment,
  person_id int(11),
  address varchar(255),
  city varchar(255),
  state varchar(255),
  zip int(9),
  PRIMARY KEY (id)
);

プライマリー・キーと外部キーについてはRailsの規則に従ったので、コンフィギュレーションは無料で手にすることができます。今度はアドレスのリレーションシップをサポートするようにperson.rbを変更します。

class Person < ActiveRecord::Base
  has_one :address
  validates_presence_of :email
end

そしてapp/models/address.rbを作成します。

class Address < ActiveRecord::Base
  belongs_to :person
end

Rubyが初めての読者のために、この構文を説明しましょう。belongs_to :personは、シンボルをパラメーターとするメソッドなのです。メソッド定義ではありません。(とりあえず、シンボルは不変ストリングだと考えてください。)belongs_toメソッドは、addressにpersonという関連付けを追加するメタプログラミング・メソッドです。この動作を見てみましょう。コンソールが実行している場合には一旦コンソールを終了し、ruby script/consoleを使って再起動します。次に、下記のコマンドを入力します。

>> person = Person.new
>> person.email = "bruce@tate.com"
>> address = Address.new
>> address.city = "Austin"
>> person.address = address
>> person.save
>> person2 = Person.find_by_email "bruce@tate.com"
>> person2.address.city
=> "Austin"

リレーションシップを説明する前に、findメソッド、find_by_emailをもう一度見てください。アクティブ・レコードは、各属性に対してカスタム・ファインダーを追加します。(この説明は少し簡略化しすぎていますが、とりあえずはこの説明で我慢してください。)

さて、最後のリレーションシップを見てください。has_one :addressはAddressというタイプのインスタンス変数をpersonに追加します。このaddressも永続性を持っています(コンソールからAddress.find_firstを入力すれば検証することができます)。つまりアクティブ・レコードは、積極的にリレーションシップを管理しています。

また、単純な1対1の関係だけに制限されているわけではありません。person.rbを次のように変更します。

class Person < ActiveRecord::Base
has_many :addresses
validates_presence_of :email
end

addressをaddressesと複数にすることを忘れないでください。今度はコンソールから、下記のコマンドをタイプします。

>> load 'app/models/person.rb'
>> person = Person.find_by_email "bruce@tate.com"
>> address = Address.new
>> address.city = "New Braunfels"
>> person.addresses << address
>> person.save
>> Address.find_all.size
=> 2

person.addresses < addressコマンドは、addressesの配列にaddressを追加します。アクティブ・レコードは、(ご想像した通り)2番目のaddressをpersonに追加しています。データベースには、もう1つのレコードがあることが検証されています。つまりhas_manyはhas_oneのように動作しますが、各Personにaddresesの配列を追加するのです。実際、アクティブ・レコードを使うと、様々なリレーションシップを持つことができます。下記はその例です。

  • belongs_to(多対1)
  • has_one(1対1)
  • has_many(1対多)
  • has_and_belongs_to_many(多対多)
  • inheritance 英語のまま
  • acts_as_tree英語のまま
  • acts_as_list英語のまま
  • composition(1つ以上のクラスを1つのテーブルにマップする)

アクティブ・レコードを学ぶことによって、私はパーシスタンスに関する理解を大いに深めることができました。そして、ラッピング手法は必ずしも劣った方法ではなく、単に異なるだけなのだ、ということを学びました。私はまだまだ、一部の問題(cruftyレガシー・スキーマなど)に関するマッピング・フレームワークについて学ぶ必要があります。アクティブ・レコードが対象とするニッチは非常に大きく、今後アクティブ・レコードがサポートするマッピングが改善されるにつれ、アクティブ・レコードも改善されて行くと思います。

また私は、パーシスタンス・フレームワークが効果的であるためには、その言語の特性を生かすべきだということも学びました。Rubyは非常に反映的(reflective)であり、ある形式のリフレクションを使ってデータベース・システム・テーブルの定義をクエリーします。

しかし、この後すぐに分かる通り、私はアクティブ・レコードだけでRailsのパーシスタンスを経験したわけではありません。


マイグレーションによって、スキーマを独立に進化させる

私はアクティブ・レコードを学ぶにつれ、2つの問題に苦しむようになりました。アクティブ・レコードを使うと、create-table SQLスクリプトを構築せざるを得ず、そのため個々のデータベース実装に拘束されてしまうのです。また開発中には頻繁にデータベースを削除する必要がありましたが、そのため、大きな変更を行う度に全テスト・データをインポートせざるを得ませんでした。私は、実稼働後の最初の変更を躊躇していました。そこに、実稼働データベースへの変更を処理するRuby on Railsのソリューションである、マイグレーション(migration)が登場するのです。

マイグレーションの例

Railsのマイグレーションでは、データベースに対する大きな変更毎にマイグレーションを作成することができます。この記事のアプリケーションでは、2つのマイグレーションを持つことができます。この実際を見るために、2つのファイルを作成します。まず、db/migrate/001_initial_schema.rbというファイルを作成し、次のようにします。

class InitialSchema < ActiveRecord::Migration
  def self.up
    create_table "people" do |table|
      table.column "first_name", :string, :limit => 255 
      table.column "last_name", :string, :limit => 255 
      table.column "email", :string, :limit => 255 
    end
  end
  def self.down
    drop_table "people"
  end
end

そして002_add_addresses.rbに、これを追加します。

class AddAddresses < ActiveRecord::Migration
  def self.up
    create_table "addresses" do |table|
      table.column "address", :string, :limit => 255
      table.column "city", :string, :limit => 255 
      table.column "state", :string, :limit => 2
      table.column "zip", :string, :limit => 10
      table.column "person_id", :integer
    end
    Person.find_all.each do |person|
      person.address = Address.new
      person.address.address = "Not yet initialized"
      person.save
    end
  end

  def self.down
    drop_table "addresses"
  end
end

下記をタイプすると、マイグレート・アップすることができます

rake migrate

rakeはJavaのantのようなものです。Railsには、マイグレーションを実行するmigrateというターゲットがあります。このマイグレーションは、スキーマ全体を追加します。とりあえず何人かの人(person)を追加しますが、まだアドレスについては気にしないでください。

ここで仮に、皆さんがひどい間違いをしてしまい、以前のバージョンにマイグレート・ダウンしなければならない、と思ってください。下記をタイプします。

rake migrate VERSION=1

このコマンドは、最初のマイグレーション(ファイル名の中のバージョン番号で指定されています)に対してAddAddresses.downメソッドを適用しています。マイグレート・アップでは、必要なマイグレーション全てに対して、数字の順にupメソッドを呼びます。マイグレート・ダウンでは、逆の順でdownメソッドを呼びます。データベースを見ると、peopleテーブルしかありません。アドレスが削除されています。つまりmigrateを使うと、必要に応じてマイグレート・アップ、マイグレート・ダウンができるのです。

マイグレーションにはもう1つの機能、つまりデータ処理があります。再度、下記をタイプしてマイグレート・アップします。

rake migrate

このコマンドはAddAddresses.upを実行し、実行する中で、各PersonオブジェクトをActive Recordアドレスで初期化します。この振る舞いは、コンソールで確認することができます。Personオブジェクトを追加すると、Addressオブジェクトも追加されています。新しいコンソールを開き、人(person)の数とアドレス・データベース行数を数えます(下記)。

>> Address.find_all.size
>> Person.find_all.size

つまり、マイグレーションは、スキーマとデータの両方を器用に処理するのです。今度は、こうした概念が、Javaの場合とどのように関連するのかを見てみましょう。


Javaパーシスタンス

Java技術でのパーシスタンスの歴史は、魅力的であると同時に悲劇的であり、そして希望に満ちたものでした。長年、Java言語が選択したコア・パーシスタンス・フレームワーク(つまりEJB(Enterprise JavaBeans)のバージョン1と2)は不適切であったため、アプリケーションは苦闘を余儀なくされ、ユーザーは幻滅しました。HibernateとJDO(Java Data Objects)は、どちらも新しいEJBパーシスタンスと共通パーシスタンス標準の基礎をなすものですが、これらによってJavaコミュニティーの中にORM(object-relational mapping)が生まれ、今やJavaを使うこと自体がずっと楽しいものになりました。

マッピング

JavaコミュニティーとORM(別名マッピング・フレームワーク)との恋愛関係は7年間も続いています。基本的にマッピングの手法を利用すると、ユーザーはJavaオブジェクトとデータベース・オブジェクトとを独立に定義でき、また両者の間にマップを構築することができます。これを図1に示します。


図1. マッピング・フレームワーク
マッピング・フレームワーク

Java言語は、まず統合言語であることが多いため、マッピングはcruftyレガシー・システムを統合する際に重要な役割を果たします(そのシステムが、たとえオブジェクト指向言語が登場するずっと以前に作られたものであっても)。今やJavaコミュニティーでは、信じられないほどマッピングを多用しています。今日では、典型的なJavaプログラマーは、ごく基本的な問題を解決するためにさえORMを利用しています。マッピングが好まれる理由は、Javaのマッピング実装が、その対抗となる手法、つまりラッピング・フレームワークよりも優れているためです。

しかし、だからといってラッピング・フレームワークの力を過小評価すべきではありません。ラッピング・フレームワークは、データベース・テーブルの周りを薄いラッパーで覆い、データベース行をオブジェクトに変換するのです(図2)。


図2. ラッピング・フレームワーク
ラッピング・フレームワーク

マップが必要のない場合には、マッピング・レイヤーは大きなオーバーヘッドを生じますが、Javaのラッピング・フレームワークは復活の兆しを見せているようです。Springフレームワークでは、JDBCラッピングを行うことができ、またエンタープライズ統合に必要なあらゆる機能を統合することができます。またiBATISは、テーブルではなくSQLステートメントの結果をラップすることができます(参考文献)。どちらのフレームワークも、私の意見では素晴らしい機構であり、まだ過小評価されていると思います。通常のJavaマッピング・フレームワークでは、Javaのラッピング・フレームワークでは手動で行わざるを得ないことを、自動的に行うことができるのです。

Javaでの必要性

Javaプラットフォームは、既に最先端のマッピング・フレームワークを誇っています。しかし私は、今やJavaプラットフォームには革新的なラッピング・フレームワークが必要だと思っています。アクティブ・レコードは、言語機能によってRailsクラスをオンザフライで拡張します。Javaフレームワークでも、アクティブ・レコードが提供するものの一部をシミュレートすることはできるかも知れません。しかしアクティブ・レコードのようなものを作ることは非常に難しく、現在のJava規則の一部を破る必要があるかも知れません。例えば次のような規則です。

  • パーシスタンス・ソリューションは、Java POJO(plain old Java object: 昔ながらの単純Javaオブジェクト)のみを対象にすべきである。まず何よりも、データベースの内容を基にプロパティーを作成することは困難です。ドメイン・オブジェクトには別のAPIがあるかも知れません。person.get_nameを呼んでプロパティーを設定する代わりに、person.get(name) を使う必要があるかも知れません。静的型チェックというコストを払った上で、データベースに駆動されるメタデータで構成されたクラスを得るのです。

  • パーシスタンス・ソリューションは、XMLまたは注釈(annotation)でコンフィギュレーションを表現する必要がある。Railsはこれとは逆に、意味のあるデフォルトを使った命名規則を強制しているため、ユーザーは大幅に繰り返しを減らすことができます。またデフォルトは、必要に応じて追加のコンフィギュレーション・コードを使ってオーバーライドできるため、コストは大したことはありません。Javaフレームワークは、『コンフィギュレーションよりも規則優先』というRailsでの仕組みを容易に採用することができます。

  • スキーマ・マイグレーションは、パーシスタント・ドメイン・モデルによって駆動すべきである。Railsはマイグレーションに関して、これとは逆です。これによる大きな利点は、データとスキーマの両方をマイグレーションできることです。またRailsでは、マイグレーションによって、リレーショナル・データベースのベンダーに依存する必要がなくなります。またRailsの戦略では、パーシスタンス戦略をスキーマ・マイグレーションの問題から分離することができます。

Railsは、Javaフレームワークの設計者が神聖なものと思いがちな、そして長年に渡って確立されてきた、こうした規則を破っています。Railsは作業スキーマとして始まっており、スキーマを反映してモデル・オブジェクトを構築します。Javaのラッピング・フレームワークでは、同じ手法は無理かも知れません。その代わり、Javaが静的型定義をサポートしているとことを利用して(また、こうした型を認識し、またコード完了などの機能を提供するツールを利用して)、作業モデルとして開始し、Javaのリフレクションと素晴らしいJDBC APIを使って、この作業モデルをデータベースにまで動的に強制することができます。

RIFEが約束するもの

新しいJavaラッピング・フレームワークとして洗練されつつあるものに、Geert Bevin の作成によるRIFE(そして、そのサブプロジェクトであるRIFE/Crud)があります(参考文献)。RIFEのパーシスタンスの中核には、次のような3つの主なレイヤーがあります。図3は、これを示したものです。

  • 単純なJDBCラッパー。テンプレートによってコールバック風のJDBC実装を提供します。
  • データベースから独立した一連のSQLビルダー。オブジェクト指向の手法によってクエリーを構築します。
  • タイプ・マッピング・レイヤー。ほとんどのSQL型を、最も関連したJava型に変換します。

図3. RIFEフレームワークでのパーシスタンス・アーキテクチャー
RIFEフレームワークでのパーシスタンス・アーキテクチャー

これらのレイヤーは、『クエリー・マネージャー』という、簡略化されたAPIが使用します。このAPIを利用すると、パーシスタンス関連のタスク(保存や更新など)に直感的にアクセスすることができます。このAPIの中の1つはJDBC専用であり、その他は、RIFEのコンテンツ管理フレームワークに関連するメタデータを検出するためのAPIに似たものとして動作します。

RIFE/Crudは、こうしたフレームワークの最上部に位置する非常に小さなレイヤーとして、すべてを一つにまとめています。RIFE/Crudは、制約(constraint)とbeanプロパティーを使って、アプリケーションのユーザー・インターフェースや、サイトの構造、パーシスタンス・ロジック、ビジネス・ロジックなどを自動的に構築します。RIFE/Crudは、RIFEのメタデータ機能を最大限に利用してインターフェースや関連APIを生成しますが、相変わらずPOPJに対して機能します。RIFE/Crudは、APIやテンプレート、コンポーネント・アーキテクチャーなどの中で明確に定義されるRIFEの統合ポイントを利用して、完全に拡張することができます。

クエリー・マネージャーのAPIは、驚くほど単純です。RIFEのパーシスタンス・モデルの実際を紹介しましょう。今ここで仮にArticleクラスがあり、その周りにテーブル構造を作り、データベースに対して2つのarticleを永続させたい、としましょう。このようなデータ・ソースに対して、下記のコードを使うとクエリー・マネージャーが得られます。

GenericQueryManager manager = GenericQueryManagerFactory.
    getInstance(datasource, Article.class);

次に、クエリー・マネージャーをインストールすることによって、データベースの中にテーブル構造を作ります。

manager.install();

これで、クエリー・マネージャーを使ってデータベースにアクセスすることができます。

Article article1 = new Article("title");
Article article2 = new Article("othertitle");

manager.save(article1);
manager.save(article2);

List articleList = manager.restore(
manager.getRestoreQuery().where("title", "=", "othertitle"));

つまりRIFEフレームワークはアクティブ・レコードと同様、『コンフィギュレーションよりも規則優先』を使うのです。Articleは、idというIDプロパティーをサポートする必要があります。あるいは、ユーザーがRIFEのAPIを使ってIDプロパティーを規定する必要があります。またRIFEは、アクティブ・レコードと同じくネイティブ言語の機能を使います。この場合、相変わらずラッピング・フレームワークはありますが、スキーマがモデルを駆動するのではなく、モデルがスキーマを駆動します。そして、(RIFEによる解決が必要な多くの問題に対して)大部分のオブジェクト・リレーショナル・マッパーよりも、APIはずっと単純です。優れたラッピング・フレームワークは、大いにJavaに役立つのです。


まとめ

アクティブ・レコードは、Javaではない言語で書かれたパーシスタンス・モデルであり、その言語の機能を大いに活用しています。今まで知らなかった人達も、ラッピング・フレームワークによってどんなことができるのか、この記事から学ぶことができたと思います。また、ここではマイグレーションについても学びました。理論的には、Javaフレームワークでもマイグレーションの概念を採用できるはずです。もちろんマッピング・フレームワークも有効なものですが、この記事から学んだことを利用してJava言語での伝統的なマッピング・ソリューションを超え、新たなラッピングの波をとらえて欲しいと思います。次回は、Web開発における継続ベース(continuation-based)の手法について解説する予定です。


参考文献

学ぶために

  • この記事の著者によるBeyond Java(Bruce Tate著、2005年O'Reilly刊)は、Javaコードの台頭と停滞について、また一部ニッチ領域においてJavaプラットフォームに対抗しうる技術について解説しています。

  • Rolling with Ruby on Rails」と「Learn all about Ruby on Rails」を読んで、インストール方法を含めてRubyとRailsについて学んでください。

  • Ruby on Rails and J2EE: Is there room for both?」(Aaron Rustad著, developerWorks, 2005年7月)は、アーキテクチャー上の主な特徴に関して、Railsと伝統的なJ2EEフレームワークとを比較対照しています。

  • Ruby off the Rails」(Andrew Glover著, developerworks, 2005年12月)の中で、Andrew Gloverは流行の表層を掘り下げ、Rubyそのもので何ができるかを解説しています。

  • Active Recordは、Ruby on Railsフレームワーク用のパーシスタンス・フレームワークです。

  • 3回シリーズのチュートリアル、「Improve persistence with Apache iBATIS and Derby」(Daniel Wintschel著, developerWorks, 2006年1月)では、最高のJavaラッピング・フレームワークの1つであるiBATISのすべてを学ぶことができます。

  • The Spring series, Part 2: When Hibernate meets Spring」(Naveen Balani著, developerWorks, 2005年8月)は、Hibernateを使う上での最高の組み合わせ、つまりSpringとHibernateとの組み合わせについて解説しています。

  • Java technologyゾーンには、Javaプログラミングのあらゆる面を網羅した記事が他にも豊富に用意されています。

製品や技術を入手するために

  • RIFEフレームワークを入手してください。RIFEは、非Java言語の持つ、過激な手法の一部を採り入れています。

  • オープンソースのRuby on Rails Webフレームワークをダウンロードしてください。

  • RubyプロジェクトのWebサイトからRubyを入手してください。

議論するために

著者について

Photo of Bruce Tate

Bruce Tate氏は、独立コンサルタント兼執筆者です。彼は12年間IBMに勤め、Javaのproof-of-conceptチームなどの様々な仕事に携わりました。Tate氏は、IBMで、Austinのあるスタートアップのためにソリューション開発組織を運営していましたが、その後IBMを退職し、J2Life, LLC という独自の事業を立ち上げました。彼は、Bitter Javaを含め、Javaアンチパターンに関する3冊の書籍を執筆しました。彼の連絡先は、bruce.tate@j2life.comです。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology
ArticleID=219187
ArticleTitle=境界を越える: アクティブ・レコードを探る
publish-date=03072006
author1-email=bruce.tate@j2life.com
author1-email-cc=

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。