アクティブレコードテンプレートの例
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は、ビジネスロジックを置き換える単なるスタブメソッドです。
アクティブレコードの利点
- オブジェクトのプロパティがデータベース内の列に直接関連している場合、Active Recordを使用したコードの記述は迅速かつ簡単です。
- 保存は1か所で行われるため、その仕組みを簡単に習得できます。
アクティブレコードの欠点
- Active RecordモデルはSOLIDの原則に違反しています。 特に、単一責任の原則( SRP - SOLID原則の「S」)。 原則によれば、ドメインオブジェクトには責任のゾーンが1つだけ、つまり独自のビジネスロジックのみが必要です。 それを呼び出してデータを保存することにより、追加の責任ゾーンを追加し、オブジェクトの複雑さを増し、そのサポートとテストを複雑にします。
- データストレージの実装は、ビジネスロジックと密接に関連しています。つまり、後で別の抽象化を使用してデータを保存する場合(たとえば、データベースではなくXMLファイルにデータを保存する場合)、コードリファクタリングを行う必要があります。
データマッパーの例
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の利点
- 各オブジェクトには独自の責任範囲があり、それにより、 SOLIDの原則に従い、各オブジェクトをシンプルかつ重要なものにします。
- ビジネスロジックとデータストレージは疎結合であり、XMLファイルまたはその他の形式にデータを保存する場合は、ドメインオブジェクトに触れることなく新しいマッパーを簡単に作成できます。
データマッパーの欠点
- コードを書く前に、もっと考えなければなりません。
- その結果、管理するオブジェクトが増え、コードとそのデバッグが少し複雑になります。
サービスオブジェクト
データマッパーデザインパターンを使用する場合、呼び出し元はマッパーとビジネスオブジェクトを選択し、それらをリンクする必要があります。 これがコントローラーの呼び出しコードである場合、最終的にモデルがコントローラーにリークし、サポートとユニットテストで大きな問題を引き起こす可能性があります。 この問題は、サービスオブジェクトを導入することで解決できます。 サービスはコントローラーとモデルの間のゲートウェイであり、必要に応じてドメインオブジェクトをマッパーに接続します。
MVCのMは、モデルオブジェクトではなく、モデル抽象化のレイヤーであることに注意してください。 したがって、1つのモデルに複数のタイプのオブジェクトが存在する可能性があります(上記の例では、単一のモデルとして機能するサービスオブジェクト、ドメインオブジェクト、およびマッパーオブジェクトを持つことができます)。 一方、Active Recordモデルを使用する場合、モデルは1つのオブジェクトのみで表現できます。
ユースケース
Active Recordオブジェクトは歴史的に非常に人気があります。なぜなら、それらはよりシンプルで、理解しやすく、書くのが速いからです。これが多くのフレームワークとORMがデフォルトでActive Recordを使う理由です。
データストレージレイヤーを変更する必要がないと確信している場合(たとえば、INIファイルであるオブジェクトを処理している場合)、またはビジネスロジックがあまりない非常に単純なオブジェクトを処理している場合、または、すべてを少数のクラスに保持することを好む場合は、Active Recordテンプレートが必要です。
Data Mapperを使用すると、コードのテストとメンテナンスがよりクリーンで簡単になり、柔軟性が向上します-これの代償-複雑さが増します。 あなたがそれを使用しようとしなかった場合、それをチャンスを与えてください-あなたはそれを気に入るはずです。
これは、 ラッセルウォーカーによる記事の翻訳です。