7

私はドメインモデル、POCO、DDDに慣れていないので、まだいくつかのアイデアに頭を悩ませようとしています。

私がまだ理解できなかったことの1つは、ドメインモデルをシンプルでストレージに依存しないように保ちながら、データに対して豊富な方法でいくつかのクエリを実行できるようにする方法です。

たとえば、OrdemItemのコレクションを持つエンティティOrderがあるとします。なんらかの理由で最も安い注文アイテム、または現在在庫がない注文アイテムのリストを取得したいのですが。私がしたくないのは、ストレージからすべての注文アイテムを取得し、後でフィルタリングすることです(高すぎる)ので、どういうわけか「SELECT .. WHERE ITEM.INSTOCK=FALSE」タイプのdbクエリを使用することになります。そのSQLクエリをエンティティに含めたくない、またはそれがLinq2SQLのNHibernateクエリのように特定のプラットフォームに結びつくかどうかのバリエーションは必要ありません。その場合の一般的な解決策は何ですか?

4

5 に答える 5

3

ドメイン オブジェクトはストレージから独立している必要があります。Repostiory パターンまたは DAO を使用してオブジェクトを永続化する必要があります。そうすれば、関心の分離が強制され、オブジェクト自体はそれがどのように格納されているかを知ることができなくなります。

理想的には、クエリの構築をリポジトリ内に配置することをお勧めしますが、その中で ORM を使用します。

Martin Fowler によるリポジトリ パターンの定義は次のとおりです。

于 2009-02-06T19:04:13.510 に答える
3

エンティティは、ドメインの「単位」です。リポジトリとサービスはそれらを参照しますが、その逆はありません。このように考えてみてください: DMV をポケットに入れて持ち歩いていますか?

OrderItem集約ルートではありません。リポジトリからアクセスできないようにする必要があります。その ID は anOrderに対してローカルです。つまり、Orderについて話すときは常に an がスコープ内になりますOrderItem

クエリのホームを見つけるのが難しいため、サービスについて考えるようになりました。この場合、それらは、それ自体が知るのが難しい、についての何かを表します。OrderOrder

ドメイン プロジェクトでインテントを宣言します。

public interface ICheapestItemService
{
    OrderItem GetCheapestItem(Order order);
}

public interface IInventoryService
{
    IEnumerable<OrderItem> GetOutOfStockItems(Order order);
}

データ プロジェクトで実装を宣言します。

public class CheapestItemService : ICheapestItemService
{
    private IQueryable<OrderItem> _orderItems;

    public CheapestItemService(IQueryable<OrderItem> orderItems)
    {
        _orderItems = orderItems;
    }

    public OrderItem GetCheapestItem(Order order)
    {
        var itemsByPrice =
            from item in _orderItems
            where item.Order == order
            orderby item.Price
            select item;

        return itemsByPrice.FirstOrDefault();
    }
}

public class InventoryService : IInventoryService
{
    private IQueryable<OrderItem> _orderItems;

    public InventoryService(IQueryable<OrderItem> orderItems)
    {
        _orderItems = orderItems;
    }

    public IEnumerable<OrderItem> GetOutOfStockItems(Order order)
    {
        return _orderItems.Where(item => item.Order == order && !item.InStock);
    }
}

この例は、任意の LINQ プロバイダーで機能します。あるいは、データ プロジェクトで NHibernate のISessionandICriteriaを使用して、汚い作業を行うこともできます。

于 2009-02-11T01:37:27.383 に答える
2

私がこのスタイルの設計を理解しているので、クエリを OrderItemRepository (またはおそらくより適切には OrderRepository) オブジェクトのメソッドにカプセル化します。このオブジェクトの責任は、一方の側で DB と通信し、もう一方の側で OrderItem オブジェクトを返すことです。リポジトリは、DB の詳細を OrderItem インスタンスの消費者から隠します。

于 2009-02-06T18:58:50.853 に答える
0

「在庫のないOrderItemのみを含む注文」について話すのは意味がないと私は主張します。「注文」(私が推測する)は、クライアントが注文したものの完全なリストを表します。Order自体を処理しなくなったリストをフィルタリングしている場合は、OrderItemのフィルタリングされたリストを処理しています。

問題は、注文を本当に集約ルートとして扱いたいのか、それともデータアクセス層からOrderItemの任意のリストを取得できるようにしたいのかということになると思います。

データベースから戻ってきたアイテムをフィルタリングするのはコストがかかりすぎるとおっしゃっていましたが、注文ごとに数百または数千のOrderItemを平均していない限り(または、大量のOrderItemを処理することに特に集中的な何かがある場合)、時期尚早に最適化を試み、必要以上に物事を困難にしている。Orderをドメインロジックの集約ルートおよびフィルターとして残すことができれば、モデルの操作がよりクリーンになると思います。

それが本当に当てはまらず、データベースでフィルタリングする必要がある場合は、「在庫のないこの注文のすべてのOrderItemを教えてください」などのクエリを提供する別のOrderItemリポジトリを用意することを検討してください。次に、それらは完全なOrderではなく、OrderItemのフィルター処理されたコレクションであるため、 IList<OrderItem>(またはIEnumerable<OrderItem>)として返します。

于 2009-02-11T02:17:59.453 に答える
-2

サービス層で。

于 2009-02-11T01:51:07.100 に答える