注: 以下の例は C# ですが、この問題は特定の言語に固有のものではありません。
そのため、 S# Architectureのバリアントを使用してオブジェクト ドメインを構築しています。なじみのない人のために、また読む時間を節約するために、永続化レイヤーとの間のロードを担当するドメイン オブジェクトごとに Data Access Object Interface を用意するという単純な考え方があります。特定のオブジェクトをロード/保存するために必要なすべてのものは、そのオブジェクトのデータ アクセス インターフェイスを依存関係として受け入れます。したがって、たとえば、製品が必要に応じて購入した顧客を遅延ロードする次のようにすることができます。
public class Product {
private ICustomerDao _customerDao;
private Customer _customer;
public Product(ICustomerDao customerDao) {_customerDao = customerDao;}
public int ProductId {get; set;}
public int CustomerId {get; set;}
public Customer Customer {
get{
if(_customer == null) _customer = _customerDao.GetById(CustomerId);
return _customer;
}
}
public interface ICustomerDao {
public Customer GetById(int id);
}
2 つのオブジェクトが相互にロードできる必要がある状況に到達するまでは、これで問題ありません。たとえば、上記のように、製品がその顧客を遅延読み込みできる必要があるだけでなく、顧客が自分の製品のリストを取得できる必要がある多対 1 の関係です。
public class Customer {
private IProductDao _productDao;
private Product[] _products;
public Customer(IProductDao productDao) {_productDao = productDao;}
public int CustomerId {get; set;}
public Product[] Products {
get{
if(_products == null) _products = _productDao. GetAllForCustomer(this);
return _products;
}
}
public interface IProductDao {
public Product[] GetAllForCustomer(Customer customer);
}
これは非常に一般的な状況であることは知っていますが、私はこれに比較的慣れていません。私のつまずきは、データ アクセス オブジェクトを実装するときに何をすべきかということです。Customer は IProductDao に依存しているため、CustomerDao の実装も必要ですが、逆もまた真であり、ProductDao は ICustomerDao に依存する必要があります。
public class CustomerDao : ICustomerDao {
private IProductDao _productDao;
public CustomerDao(IProductDao productDao) {_productDao = productDao;}
public Customer GetById(int id) {
Customer c = new Customer(_customerDao);
// Query the database and fill out CustomerId
return c;
}
}
public class ProductDao : IProductDao {
private ICustomerDao _customerDao;
public ProductDao (ICustomerDao customerDao) {_customerDao = customerDao;}
public Product[] GetAllForCustomer(Customer customer) {
// you get the idea
}
}
そして、ここに問題があります。IProductDao なしで CustomerDao をインスタンス化することはできません。制御コンテナー (Castle Windsor) の反転は、循環依存関係にヒットし、チョークします。
私は、DAOオブジェクト自体を遅延ロードすることを含む当面の解決策を思いつきました(これを回答として投稿します)が、私はそれが好きではありません。この問題に対する定評のある解決策は何ですか?
編集:上記は私が実際に使用しているアーキテクチャを簡略化したものであり、誰かが実際にオブジェクトに DAO を渡すことをお勧めしていません。私が実際に行っていることに近いより良い実装は、実際のオブジェクトが非常に単純で、上記が実際には適切なフィールドを継承してオーバーライドするプロキシ オブジェクトである NHibernate の動作に似ています。