9

そのため、MVCフレームワークで永続性レイヤーをモデルから切り離す手段としてのリポジトリパターンの役割を研究してきました。これ以前は、UserModelドメインオブジェクトを保存/取得するために、アクティブレコードメソッドを直接呼び出すことがありました。

これは、新しいものを作成する必要があるリクエストのコールスタックに関して私が考えていることのスケッチですUser

ここに画像の説明を入力してください

これが私の質問です:

  1. これはリポジトリパターンの正しい実装ですか?
  2. コントローラーがリクエストからユーザーの情報を取得し、それをモデルに渡す必要があることを理解しています。それは通常どのように起こりますか?コントローラはUserオブジェクトを作成し、それをモデルに渡す必要がありますか?値の配列をモデルに渡すだけではなく、ユーザーを作成するモデルメソッドに15個の引数を渡したくないのは確かです。
  3. このパターンが実際に機能するためには、動作のない単純なデータ構造であるドメインオブジェクトが必要であるように見えます。次に、ORMを使用している場合は、ORMオブジェクトが必要になります。オブジェクトがどのように永続化されるかを説明します。最初は重複したコードのように感じるのでこれに抵抗しましたが、永続性をビジネスロジックから本当に分離しているのであれば、これは必要でしょうか?たとえば、インメモリストアを使用した場合はどうなりますか?ORMオブジェクトはもう使用しません。

私はここで正しく考えていますか?これは許容できますか。頭の中の点をつなぐのを手伝ってください。

4

2 に答える 2

19

1.これはリポジトリパターンの正しい実装ですか?

あなたがその研究をどこで行っているのかはわかりませんが、あなたはそれを間違えています。

  • ドメインオブジェクトデータマッパーから分離するためのリポジトリ

  • 「モデル」というものはありません。MVCデザインパターンのモデルは、プレゼンテーション層モデル層という主要な層の1つです。

  • また、リポジトリパターンは、ドメインとストレージロジックを単一のインスタンスに結合するアクティブレコード(アンチ)パターンと互換性がないため、重大なSRP違反が発生します。

リポジトリをいつ、どのように使用するかについて実際の例を使用するには、次の例を示します。

ドキュメント管理ツールを作成しています。このツールでは、ドキュメントを複数のソース(たとえば、ローカルSQLデータベース、SOAPサービス、キャッシュ)から取得できます。この状況では、ストレージの「ルーティング」を処理するリポジトリを作成します。これはアプリケーションの一部であり、各ドキュメントの保存/取得に使用するデータマッパーを決定します。

リポジトリの目的は、ドメインロジックをストレージとの相互作用から分離することです。上記で説明したシステムの場合、リポジトリを使用すると、大量のコード(存在する場合)を書き直すことなく、新しいデータソースを追加することもできます。ドキュメントに別のタイプのマッパーを追加するだけで済みます。

2.コントローラーはUserオブジェクトを作成し、それをモデルに渡す必要がありますか?

そもそも、コントローラー自体は何も作成しないでください。代わりに、コントローラーは、必要なオブジェクトのインスタンスを取得するためにファクトリを使用する必要があります。このファクトリは、コンストラクターまたはその他の方法でコントローラーに提供できます。これは、依存性注入と呼ばれます(詳細については、この講義をご覧ください)。

また、上記のように、モデルはレイヤーであり、特定のクラスやオブジェクトではありません。コントローラの責任は、モデル層の状態を変更することです(データをモデル層に渡すことによって)。コントローラでドメインオブジェクトとマッパー(またはリポジトリ)を直接操作することもできますが、それはコントローラのビジネスロジックの一部をリークすることを意味します。代わりにサービスを使用することをお勧めします。サービスは、前述のドメインオブジェクトとストレージ関連の構造を操作します。

新しいユーザーアカウントの作成に必要となる10以上のパラメーターの問題については、次のフットプリントでアクションがあると仮定します。

public function postUser( Request $request )
{
    ....
}

アクションが特定のRequestインスタンスで呼び出される場合、大量のパラメーターを処理する方法には2つのオプションがあります。

  1. インスタンスをデコレータでラップします。これにより、特定の配列でリクエストからデータを形成するための単一のメソッドを呼び出すことができます。次に、この配列をサービスに渡します。

  2. コントローラのアクション内に配列を作成し、データが必要な場所に渡します。

前者のソリューションは、コード全体でこのようなデータの形成が繰り返し必要になる大規模なアプリケーションに適しています。しかし、中小規模のプロジェクトでは、2番目のオプションは常識的なアプローチです。

つまり、コントローラーの仕事は、ユーザーの入力を受け取り、それをモデルレイヤーと現在のビューに配布することです。そして、そのようなアレイの形成は、この使命にぴったり合っています。

3.(..)動作のない単純なデータ構造であるメインオブジェクト、次に(..)

いいえ。ドメインオブジェクトは「単純なデータ」ではありません。これは、ドメインビジネスロジックのほとんどがアプリケーションに存在する場所です。

そして、魔法のORMを忘れてください。リポジトリを実装するための最初のステップは、ドメインとストレージロジックを分離することです。ドメインオブジェクトは検証とビジネスルールを処理し、マッパーは永続性とデータの整合性を処理します(ここの小さな例)。

あなたが認識しなければならないもう一つのことは、Webアプリケーションのリポジトリは(キャッシュを除いて)メモリ内の永続性と実際には相互作用しないということです。代わりに、リポジトリはさまざまなデータソースのマッパーをジャグリングします。

于 2012-09-10T01:04:51.303 に答える
1

コントローラはUserオブジェクトを作成し、それをモデルに渡す必要がありますか?

「それをモデルに渡す」とはどういう意味かわかりません。Userオブジェクトモデルです。「コントローラー」と「モデル」は、デザイン内の異なるレイヤーを表します。これらは特定のオブジェクトではなく、UserModel前述のように別個のオブジェクトがあってはなりません。

リポジトリインターフェイス自体は一般にモデルの一部と見なされますが、ドメインオブジェクトはそれ自体を保存するべきではありません。これは、コントローラで実行する必要があります。

コントローラの仕事は、リクエストを解釈してUserオブジェクトを作成し、リポジトリを使用してユーザーを保存することです。

$user = new User(...); // based on Request
$repository->save($user);

私には、動作のない単純なデータ構造であるドメインオブジェクトが必要になるように見えます

これは真実ではありません。ドメインオブジェクトの動作をカプセル化することができ、カプセル化する必要があります。永続性が実際にどのように実装されるかについては、優れたORMがほとんどの詳細を処理する必要があり、手動で追加のクラスを作成する必要はありません。

于 2012-09-10T00:43:07.977 に答える