Active Record は、以下の全ての責務を兼ねるひとつのオブジェクトを設けるパターンです。
- Domain Model の意味表現に使われる要素
- Row Data Gateway によるデータベースアクセス
- Table Module によるドメインロジック
ひとつのクラスがテーブルに関する知識を全て持つのが、Active Record の特徴です。これにより、ひとつのレコードに関する大部分のロジックが、オブジェクトインスタンス内のスコープに閉じることになります。無関係な行への誤ったアクセスを予防できる、オブジェクト指向的なプログラミングに慣れていないプログラマーにとっても平易なロジック記述が可能になる、といったメリットがあります。
Row Data Gateway としての操作を外に露出させず、できるだけ内部で利用して Table Module として利用できる形にすることで、Transaction Script のリファクタリング手段としての有効性が示唆されています。この点を逆に言うと、Active Record の凝集性を意識せずに設計すると、そのクライアントコードは実質的に Transaction Script になるという意味です。クライアントコードは Active Record の内部と異なり、すべての Active Record オブジェクトへのアクセス権を持っており、それはデータベースに任意の SQL を直接発行できるのと同じ意味になるからです。
Active Record のデメリットは、柔軟なドメインモデルを構築できない点です。オブジェクトは必ずテーブルに対応しなければならないため、Domain Model はテーブルの構造にダイレクトに依存します。これは特に、蓄積されたデータが増えてデータベースのスキーマ変更が困難になってくると、モデルのリファクタリングを急激に困難にしてしまうデメリットとして現れてきます。この不自由への覚悟ができるぐらいアプリケーションが単純かどうかを、よく考えて採用しなければならないパターンです。
プロジェクトによりますが、Active Record をサポートするフレームワークを利用すると、Domain Model がフレームワークに強く依存してしまう点が問題になる場合もあります。フレームワークが動作する条件を満たさないと、単体テストができないからです。データベースとの接続を確立しないと動作しないフレームワークもあります。現在では OSS のデータベースを Docker などで簡単に起動できますが、昔は Oracle の開発用ライセンスがなく、データベースの実物を動かせない開発者もいました。
いっぽう、Data Mapper は、中間的な「マッピング」層によって、何者からも独立した平易な Domain Model のエンティティ (ビジネスロジックが操作する対象物としてのオブジェクト) と、データベースのテーブル構造との直接的な繋がりを分離するパターンです。
プログラミング言語で表されるモデルの都合と、リレーショナルデータベースの都合は、似ている事と全く似ていない事があります。Domain Model のビジネスロジックが高度になればなるほど、似ていないことによる不都合の方が目立ってきます。このギャップを埋めるのにかかる面倒な作業は、インピーダンスミスマッチ (異なる電気回路などを接続したとき発生するエネルギーロスの原因) に例えられます。このミスマッチによるロスを緩和し、双方の都合が良いようにデータを翻訳して同期するのが、Data Mapper の目的です。
Active Record は、広義ではオブジェクトリレーショナルマッパー (ORM) に分類されることもありますが、PoEAA の観点では Active Record を ORM みなしません。独立した Domain Model と、独立したリレーショナルデータベースがあり、それを外部からマッピングによって繋ぐアーキテクチャを、ORM と呼びます。
何がインピーダンスミスマッチなのか、マッピングでどのように解決するのかについては、「オブジェクトリレーショナル振る舞いパターン」および「オブジェクトリレーショナル構造パターン」で詳しく述べられています。
Data Mapper を利用することで得られる即物的なメリットは、データモデルを使う単体テストに影響する外部要因が、ゼロになることです。ただし、手作業でマッピングのメカニズムを作ると、そこを自動テストのカバレッジに含むのは (Active Record と同じ理由で) とても困難かつ退屈な作業です。確実に手作業の量が少ないと確信できる場合以外は、サードパーティのマッピングフレームワークを利用するのがオススメです。
どのようなドメインロジック記述の方針を選ぶべきかと同じように、データゲートウェイか、Active Record か、Data Mapper かの選択は、単純な優劣で比べるべきものではありません。
- 直接的な SQL のチューニングが重要になる場合は、薄いデータゲートウェイが有利になります。
- 単一レコードに着目した比較的単純な手続きが多い場合は、Domain Model に Active Record を入れ込むのが効率的です。
- たとえばテスト駆動開発で(あるいは同じような設計方針で)、小さな問題に分解した抽象モデルの連携によって Domain Model を設計したい場合は、Data Mapper が最適な選択になります。