4

最近、自分のアーキテクチャーのメソッドや関数が適切な位置にあるかどうかを判断するのに苦労しました。正しいレイヤーに。Martin Fowler のリポジトリ パターンに従って、サービス レイヤーをデータベースから分離したいと考えています。

Martin Fowler が彼の Web サイトで説明している定義には、次のように書かれています。

リポジトリは、ドメイン レイヤーとデータ マッピング レイヤーの間を仲介し、メモリ内のドメイン オブジェクト コレクションのように機能します。

問題は、たとえばすべての請求書の合計を取得する必要がある多くの要件があることです。お分かりのように、すべての請求書の合計はスカラー値です。Martin Fowler の定義に従う場合、私がすべきことは、リポジトリ レイヤーからドメイン オブジェクトのリストを返す関数を作成することです。このリストは、オブジェクトをループ スローして合計を計算するサービス レイヤーによって受信されます。このパターンの意味の本質を理解していない可能性もあります...

保守性が優れているため、アプリケーションを設計する際にパフォーマンスを気にする必要がないことはわかっていますが、その場合、10 進値を返す関数をリポジトリ レイヤーで作成しないことは、開発とパフォーマンスにおいて完全に時間の無駄であると考えています。請求書の合計に対応し、サービス層からこれと同じ値を返します。ORM を使用して遅延読み込み戦略を追加できたとしても、オブジェクトのリストを具体化してから単一のプロパティを使用するだけではやり過ぎです。

リポジトリ レイヤーからスカラー値を返すのは正しいですか、それとも誘惑に抵抗し、常にこのレイヤーからドメイン オブジェクトを返し、サービス レイヤーですべてのビジネス ロジックを処理する必要がありますか?

また、プレゼンターがサービス レイヤーを呼び出してからリポジトリ レイヤーを呼び出す代わりに、私のリポジトリを直接呼び出す場所もたくさんあります。正しいです; このリポジトリ パターンをサービス レイヤーの外部で呼び出しても問題ありませんか?

これは Demeter の法則と完全に矛盾するため、リポジトリ レイヤーから IQueryable の結果を返したくないことに注意してください。

また、このレイヤーを完全に単体テストできるようにしたいので、クエリをサービスレイヤーに直接設定したくありません。統合テストを行っていません。

4

2 に答える 2

2

この問題は、CQRS(概念として)を使用して簡単に解決できます。UI(またはMVCを使用している場合はコントローラー)が使用できる専用のクエリ専用リポジトリーを用意します。そのリポジトリは、データベース(ORMエンティティは実際には重要ではありません)に直接クエリを実行し、必要なものを返すことができます。

モデルを更新する場合にのみ、「重い」ドメインオブジェクトと対応するリポジトリを保持します。

于 2012-04-24T15:12:54.873 に答える
1

同様の問題があり、最終的にベースおよび派生リポジトリ インターフェイスができました。ベースには Fetch 、 Update などの標準メソッドがあり、派生インターフェイスには特定のメソッドがあります(この場合はスカラー値を取得します)。

public interface IRepository { ... }

public interface IInvoiceRepository : IRepository 
{ 
  int GetTotal(); 
}

次に、インターフェースを実装する InvoiceRepository クラスを作成します。IInvoiceRepository 型の依存性注入を取得する InvoiceBusinessObject など、別のクラスにビジネス ロジックを実装することをお勧めします (コンストラクターでパラメーターを使用します)。ビジネス層で実装を使用しないでください。

public class InvoiceBusinessObject
{
  private IInvoiceRepository rep;

  public InvoiceBusinessObject(IInvoiceRepository rep)
  {
    this.rep = rep;
  }

  public int GetTotal()
  {
    return rep.GetTotal();
  }
}

サービス層は InvoiceRepository クラスをインスタンス化し、そのインスタンスをビジネス オブジェクト クラスに挿入できます。

public int GetTotalFromService()
{
  IInvoiceRepository rep = new InvoiceRepository();
  InvoiceBusinessObject bizObj = new InvoiceBusinessObject(rep);
  return bizObj.GetTotal();
}
于 2012-04-24T06:05:01.517 に答える