0

私はPOCプロジェクトを誰かに割り当て、コマンドクエリの分離、制御の反転(依存性注入を使用)、およびリポジトリパターンの両方を実装するように依頼しました。「誰か」が私にPOCソリューションプロジェクトをくれましたが、これがその方法であるかどうかはわかりません。ここでPOCプロジェクトについて簡単に説明します

  • このプロジェクトは、プレゼンテーション層(PL)、ビジネスロジック層(BLL)、およびデータアクセス層(DAL)の単純な3層アプリケーションです。各層は個別のプロジェクトです
  • プレゼンテーション層はWebアプリケーションであり、BLLとDALはクラスライブラリプロジェクトです。
  • ビジネスレイヤーには、定義済みのリポジトリインターフェイスがあります。BLLライブラリの参照がDALプロジェクトに追加され、DALプロジェクト内には、リポジトリインターフェイスを実装する具象クラスがあります。これは、制御の反転が適用される方法です
  • Command-Query-Separationが実行されるため、ビジネスレイヤーのリポジトリインターフェイスは、Add/UpdateメソッドとDeleteメソッドのみを宣言します。読み取りの場合、DALには直接「読み取り」インターフェースがあり、DALにはこれらのインターフェースを実装する具象クラスがあります。
  • プレゼンテーション層には、BLLライブラリとDALライブラリの両方への参照が含まれています。追加/更新/削除の呼び出しは、BLLを介してDALにルーティングされますが、読み取りはDALから直接行われます。これは、読み取りを行うためにBLLをバイパスするというコマンドクエリ分離の概念に準拠していると思います。

これがすべてのセットアップ方法の図です。3つのプロジェクトがあります

  • NW.Web
  • NW.Business
  • NW.DataAccess

以下は、さまざまなレイヤーのコードのスナップショットです。

--NW.Web-

// A class in the Presentation Layer
public class CustomerPage 
{

    // Business layer Interface from  NW.Business namespace
    private ICustomerBusiness ICustB;

    //DAL Read interface from NW.DataAccess.Read namepsace
    private ICustomerRead<Guid> ICustR;

    //Constructor for the Customer Page that uses Constructor Injection
  public CustomerPage(ICustomerBusiness ICustB, ICustomerRead<Guid> ICustR)
    {
        this.ICustB = ICustB;
        this.ICustR = ICustR;
    }
}

--NW.Business-

//Declaration of business interface in the Business Layer
interface ICustomerBusiness
{
    void Persist();
}

// A class in the Business Layer that implements the business interface
public class Customer: ICustomerBusiness 
{
    //Repository interface object that will be injected by Constructor Injection.
    private ICustomerRepository ICustRep;

    public Customer(ICustomerRepository ICustRep)
    {
        this.ICustRep = ICustRep;
    }

    public void Persist()
    {

            ICustRep.AddOrUpdate();

    }
}

//Declaration of Repository interface in the Business Layer
public interface ICustomerRepository
{
    void AddOrUpdate();
    void Delete();
}

--NW.DataAccess--

public class CustomerRepository : ICustomerRepository
{

    public void AddOrUpdate()
    {
        //implementation of Add or Update
    }

    public void Delete()
    {
        //implementation of Delete
    }
}

//A Read interface in the Data Access Layer
interface ICustomerRead<T>
{
   // A read is returned as DTO since in Database this may map to more than 1 table
    CustomerDTO GetCustomerDetails(T id);
}

// An implementation of the Read Interface in the Data Access Layer
namespace NW.DataAccess.Read
{
    public class CustomerRead<T> : ICustomerRead<T> 
    {

        public CustomerDTO GetCustomerDetails(T id)
        {
           //implementation here
        }
    }
}

私の直感は、ここに何か問題があるということです。CQRSまたは少なくとも上記の実装が一部の要件に対応していないようです

  • Customer Businessオブジェクト(Customerクラス)は、内部目的(変数の初期化など)のためにデータベースから読み取る必要がある場合があります。読み取りがDAL層で直接定義されている場合、これを行う唯一の方法は、BLLでDALdllを参照することです。しかし、これは循環参照を作成し、行われるIOCに反します
  • すべてのビジネスオブジェクトに共通の読み取り要件がある場合はどうなりますか?

助言がありますか ?

4

1 に答える 1

0

一般的な概念は、「コマンド」と「クエリ」を持つことであり、それらの中でリポジトリへの依存関係を取ることができると思います。

私は実際に、各コントローラーが 1 つ以上のリポジトリーに依存して作業を完了する ASP.NET MVC プロジェクトをリファクタリングしました。それをリファクタリングしたとき、発生する必要のある特定のアクションごとに「コマンド」オブジェクトと「クエリ」オブジェクトを作成し、各コントローラーを大幅に簡素化しました。次に、これらのコマンドとクエリで、既存のリポジトリを使用してロジックを実行しました。

余計な手間のように思えるかもしれませんが、私がそうした理由は、ソリューションにもキャッシュがあったからです。キャッシング コードはごちゃごちゃしていて、あちこちにキャッシュ キーが追加されたり削除されたりしていました。すべてのデータ アクセスをコマンドとクエリに分離し、データがアクセスまたは更新されたときにドメイン イベントを発生させることで、キャッシュ管理コードを簡素化し、分離することができます。

簡単なコマンドとクエリの分離を実装する方法の概要については、このトピックに関する最近のブログ投稿を参照してください。このトピックには、セットアップを迅速化するのに役立つサンプル コードと NuGet パッケージも含まれています: http://www.nootn.com.au/2013 /03/command-query-separation-to-better.html

特に、「すべてのビジネス オブジェクトに共通の読み取り要件があるとどうなるか」という質問に答えるには、私の例のように、「DBContext」ではなく、「DBContext」の代わりに「IRepository」という一般的な依存関係を持っているクエリ クラスとコマンド クラスを想像してみてください。これが、ビジネス オブジェクト間で共通の読み取り要件を「共有」する方法です。

于 2013-03-25T11:47:04.467 に答える