デザインパターンから見た
Active Record
2012/05/23 シナジーマーケティング(株) 寺岡 佑起
デザインパターンから見たActive Record
1. Active Recordパターンとは?
2. 1対1で割り当てるシンプルなルール
3. Active Recordパターンの欠点
4. 振る舞いを持つモデルクラス
5. コールバックを利用したモデルクラスの例
6. まとめ
Active RecordはRailsのMVCのModelの中心となるライブラリです。
Active RecordライブラリはSQLを意識せずにデータベースアクセスを行える非常に便利なライブラリで、その名前は「Active Recordパターン」というデザインパターンに由来しています。
Active RecordパターンをRubyで実装したライブラリが、Railsで使われているActive Recordライブラリなのです。
以降では、RubyのORマッピングライブラリを「Active Recordライブラリ」、デザインパターンを「Active Recordパターン」と呼ぶことにします。
では、その基本思想となるActive Recordパターンとは、一体どんなデザインパターンなのでしょうか。
本稿では、Active Recordパターンについて考えながら、Active Recordライブラリについて掘り下げていきたいと思います。
1. Active Recordパターンとは?
Martin Fowler氏の Patterns of Enterprise Application Architecture (邦訳)で解説されているデザインパターンのひとつで、以下のように解説されています。
- データベーステーブルまたはビューの行をラップし、データベースアクセスをカプセル化してデータにドメインロジックを追加するオブジェクト1
このパターンをRubyで自然に実装すると、以下のようなクラス設計になるでしょう。
- クラスは1つのテーブルを表す
- インスタンスはテーブルの1行を表す
- クラス、インスタンスメソッドで関連するデータ処理を行う
確かに、Active Recordライブラリの特徴と一致します。
2. 1対1で割り当てるシンプルなルール
Active Recordパターンでは、テーブルとクラス、行とインスタンス、カラムと属性2 は1対1で関連付けられます。
この「全てを1対1で割り当てる」シンプルなルールがActive Recordパターンの最大の特徴と言えます。ルールがシンプルであるということは、複雑な設定が必要ない、ということになります。
Active RecordライブラリはCoC(設定より規約)4の思想により、クラス名を元にテーブル定義を取得し、カラムのマッピングを自動的に作成します。
基底クラスを継承したクラスを作成するだけで、基本的なCRUD3 操作をこなしてしまう、非常に強力な機能を備えています。
これによって、以下の2行のコードでモデルクラスを作成できます。5
class Employee < ActiveRecord::Base end
たったこれだけの記述で、employeesテーブルのデータを自在に操ることが出来るのです。
3. Active Recordパターンの欠点
シンプルかつ強力なActive Recordパターンですが、不得手が無いわけではありません。
Active Recordパターンは、1つのクラスは1つのテーブルを表す、というある意味割り切ったルールを適用します。
このシンプルさこそ利点であり、そのまま欠点にもなってしまうのです。
Active Recordパターンではルール上、データベースの構造がそのままモデルクラスの設計になってしまうため、パフォーマンスの為の非正規化を行う場合や、逆に細部に至るまで正規化されたデータベース設計を行うと、モデルクラスは非常に扱いづらいものになってしまいます。
Active Recordパターンは性質上、クラス設計がデータベース設計に引きずられてしまうため、複雑なデータベース設計とは相性が悪いデザインパターンなのです。
ですが、Active Recordパターンのもう一つ大きな特徴により、うまく解決できる場合もあります。
1 「エンタープライズ アプリケーションアーキテクチャパターン」マーチン・ファウラー (著) , 長瀬 嘉秀 (監訳), 株式会社 テクノロジックアート (翻訳) 翔泳社 2005年
2 属性:Rubyではアクセッサメソッドがこれに該当します
3 CRUD Create(生成)、Read(読み取り)、Update(更新)、Delete(削除)のイニシャルを並べた言葉
4 CoCについては1. Ruby on Railsとはをご覧ください
5 データベース接続情報などはconfig/database.ymlで設定しておく必要があります