バックグラウンド
DDD + TDD+etcのスタック全体を実際に理解するための単純なアプリケーションを作成しようとしています。私の目標は、実行時にDALリポジトリクラスを動的に注入することです。これにより、ドメインおよびアプリケーションサービスレイヤーをテスト可能に保つことができます。私は今のところこれを達成するために「貧乏人のDI」を使用することを計画しています...それで私はスタートアップの近くの単純なコンソールアプリケーションでこれを行うでしょう:
//貧乏人のDI、実行時にDALリポジトリクラスを注入 var productRepository = new SimpleOrder.Repository.ProductRespository(); var customerRepository = new SimpleOrder.Repository.CustomerRepository(); var orderRepository = new SimpleOrder.Repository.OrderRepository(); //ApplicationServicesレイヤーのこのクラスへのコンストラクターインジェクション // SimpleOrder.ApplicationFacade OrderEntry oe = new OrderEntry(customerRepository、orderRepository、productRepository);
この依存性注入を実現するために、次の3つのリポジトリインターフェイスを作成しました。
--ICustomerRepository --IOrderRepository --IProductRespository
典型的な実装:
名前空間SimpleOrder.Domain.Interfaces {{ パブリックインターフェイスICustomerRepository {{ Customer GetCustomerById(int customerId); void SaveCustomer(顧客顧客); } }
** SaveCustomerは、ドメインレイヤーで定義されたCustomerモデルクラスを参照していることに注意してください。これは他のリポジトリの典型です。
ただし、どのプロジェクト/レイヤーに実装する必要があるかわかりません。ソリューションには5つのプロジェクトがあります。
SimpleOrder.ConsoleClient(プレゼンテーション) -ここからアプリケーションとしてドメインの特定の実装を注入したい
SimpleOrder.ApplicationFacade(アプリケーションサービス) -ドメイン内の低レベルのメソッドを調整する、分厚い高レベルの粗粒度のメソッド
SimpleOrder.Contracts- プレゼンテーションサービスとアプリケーションサービス間の通信に使用されるDTOクラス
SimpleOrder.Domain(domain / bll) -ドメインモデルクラスCustomer、Order、OrderItem、Product
SimpleOrder.Repository(dal) -リポジトリインターフェイスを実装します
私が見ている私の選択肢は次のとおりです。
オプション1: SimpleOrder.Contracts..でリポジトリインターフェースを定義します。
PRO:さまざまな懸念事項やレイヤー間で契約を共有するために作成したので、ここに所属する必要があると思います。たとえば、DTOはここで定義されます。
CON:ただし、各インターフェイスのメソッドシグネチャはドメインモデルクラスを参照します。
つまり、SimpleOrder.Domainへの参照を追加する必要がありますが、SimpleOrder.Contractsが別のプロジェクトで参照されている場合は、SimpleOrder.Domainを実行する必要があります。これは正しくないと思います。
オプション2:上記と同じシナリオですが、SimpleOrder.Contractsで各ドメインモデルクラスのインターフェイスも定義して、リポジトリインターフェイスと実際のモデルクラスの結合を解除できるようにします。
例:
名前空間SimpleOrder.Domain.Interfaces {{ パブリックインターフェイスICustomerRepository {{ ICustomer ** GetCustomerById(int customerId); void SaveCustomer(ICustomer customer); } パブリックインターフェイスICustomer {{ int CustomerId {get; セットする; } 文字列名{取得; セットする; } System.Collections.Generic.List Orders {get; } } }
影響:各ドメインモデルクラスは、関連するインターフェイスを実装する必要があります。すなわち、
パブリッククラスCustomer:SimpleOrder.Domain.Interfaces.ICustomer {{ public Customer() {{ _orders = new List(); } public int CustomerId {get; セットする; } public string Name {get; セットする; } プライベートリスト_orders; パブリック仮想リスト注文{ get {return _orders; } } }
PRO:オプション1の問題を修正します。
CON:これにより、プロジェクト内のファイルの数(および認識される複雑さ)が爆発的に増加します。これは、各ドメインクラスにインターフェイスが関連付けられているためです。
オプション3: SimpleOrder.Domainでリポジトリインターフェースを定義する
影響:実行時にSimpleOrder.ConsoleClientからアプリケーションサービスレイヤー(SimpleOrder.ApplicationFacadeプロジェクト)に具象リポジトリクラスを挿入するには、SimpleOder.ConsoleClientにもSimpleOrder.Domainへの参照が必要です。
PRO:これはオプション1も解決します
CON:プレゼンテーション層がドメイン層について多くを知ることができるようになったため、プレゼンテーション層からドメイン層を直接参照することを避けようとしていました。将来、コンソールアプリケーションをWPFまたはASP.NET MVCアプリに置き換えると、2番目以降のプレゼンテーション層の実装がアプリケーションサービス層ではなくモデルのメソッドを呼び出そうとするリスクがあります。(ただし、オプション4ではこれを考慮しています。)
オプション4:インターフェイスをSimpleOrder.Domainに配置し、SimpleOrder.ConsoleClientからSimpleOrder.Domainを参照します。
PRO:上記のすべての問題を修正します。
CON: SimpleOrder.ApplicationFacadeの高レベルの分厚いメソッドへのアクセスのみを提供する必要があるのに、プレゼンテーション層からドメイン層の低レベルのメソッドへのアクセスを直接提供するため、これは正しくありません。
質問 私はこれらのそれぞれを試しましたが、オプション4に落ち着きましたが、それは私の口に悪い味を残します。より良いオプションはありますか?私はここで正しい方向に進んでいますか?