データを保存するためのアクティブレコードとデータマッパー

これら2つの設計パターンは、Martin Fowlerの著書「Enterprise Application Templates」に記載されており、オブジェクト指向プログラミングでデータを保存する方法を表しています。



アクティブレコードテンプレートの例



class Foo { protected $db; public $id; public $bar; public function __construct(PDO $db) { $this->db = $db; } public function do_something() { $this->bar .= uniqid(); } public function save() { if ($this->id) { $sql = "UPDATE foo SET bar = :bar WHERE id = :id"; $statement = $this->db->prepare($sql); $statement->bindParam("bar", $this->bar); $statement->bindParam("id", $this->id); $statement->execute(); } else { $sql = "INSERT INTO foo (bar) VALUES (:bar)"; $statement = $this->db->prepare($sql); $statement->bindParam("bar", $this->bar); $statement->execute(); $this->id = $this->db->lastInsertId(); } } } //Insert $foo = new Foo($db); $foo->bar = 'baz'; $foo->save();
      
      





この単純化された例では、データベース記述子がFooコンストラクターに入力され(ここで依存性注入を使用すると、実際のデータベースを使用せずにオブジェクトをテストできます)、Fooはそれを使用してデータを保存します。 Do_somethingは、ビジネスロジックを置き換える単なるスタブメソッドです。



アクティブレコードの利点





アクティブレコードの欠点





データマッパーの例



 class Foo { public $id; public $bar; public function do_something() { $this->bar .= uniqid(); } } class FooMapper { protected $db; public function __construct(PDO $db) { $this->db = $db; } public function saveFoo(Foo &$foo) { if ($foo->id) { $sql = "UPDATE foo SET bar = :bar WHERE id = :id"; $statement = $this->db->prepare($sql); $statement->bindParam("bar", $foo->bar); $statement->bindParam("id", $foo->id); $statement->execute(); } else { $sql = "INSERT INTO foo (bar) VALUES (:bar)"; $statement = $this->db->prepare($sql); $statement->bindParam("bar", $foo->bar); $statement->execute(); $foo->id = $this->db->lastInsertId(); } } } //Insert $foo = new Foo(); $foo->bar = 'baz'; $mapper = new FooMapper($db); $mapper->saveFoo($foo);
      
      





この場合、Fooクラスははるかに単純であり、そのビジネスロジックのみを心配する必要があります。 彼は自分のデータを保存する必要がないだけでなく、すべてのデータが保存されたかどうかも知らず、気にしません。



Data Mapperの利点





データマッパーの欠点





サービスオブジェクト



データマッパーデザインパターンを使用する場合、呼び出し元はマッパーとビジネスオブジェクトを選択し、それらをリンクする必要があります。 これがコントローラーの呼び出しコードである場合、最終的にモデルがコントローラーにリークし、サポートとユニットテストで大きな問題を引き起こす可能性があります。 この問題は、サービスオブジェクトを導入することで解決できます。 サービスはコントローラーとモデルの間のゲートウェイであり、必要に応じてドメインオブジェクトをマッパーに接続します。



MVCのMは、モデルオブジェクトではなく、モデル抽象化のレイヤーであることに注意してください。 したがって、1つのモデルに複数のタイプのオブジェクトが存在する可能性があります(上記の例では、単一のモデルとして機能するサービスオブジェクト、ドメインオブジェクト、およびマッパーオブジェクトを持つことができます)。 一方、Active Recordモデルを使用する場合、モデルは1つのオブジェクトのみで表現できます。



ユースケース



Active Recordオブジェクトは歴史的に非常に人気があります。なぜなら、それらはよりシンプルで、理解しやすく、書くのが速いからです。これが多くのフレームワークとORMがデフォルトでActive Recordを使う理由です。



データストレージレイヤーを変更する必要がないと確信している場合(たとえば、INIファイルであるオブジェクトを処理している場合)、またはビジネスロジックがあまりない非常に単純なオブジェクトを処理している場合、または、すべてを少数のクラスに保持することを好む場合は、Active Recordテンプレートが必要です。



Data Mapperを使用すると、コードのテストとメンテナンスがよりクリーンで簡単になり、柔軟性が向上します-これの代償-複雑さが増します。 あなたがそれを使用しようとしなかった場合、それをチャンスを与えてください-あなたはそれを気に入るはずです。



これは、 ラッセルウォーカーによる記事の翻訳です。



All Articles