2009-07-17 9 views
10

これが死に至ったと考えている人は、事前に謝罪します。私はちょうど最後の数時間を探して、ここで多くの優れた記事を読んで過ごしましたが、私はまだ混乱しています。DDD、Repository&Encapsulation

私の混乱の原因は、DTOとDDDとリポジトリです。私は私のPOCOドメインオブジェクトにスマートを持たせたい、そしてリポジトリからそれらを取得したい。しかし、私はその作業をするためにいくつかのカプセル化ルールに違反しなければならないようで、DTOを頭の中に変えることができるようです。

ここでは簡単な例を示します。私たちのカタログアプリケーションでは、Partは他の多くの部品を含むパッケージです。したがって、Part POCOがIEnumerable < Part>を返す 'GetChildren()'メソッドを持つことは意味があります。それは、出て行く途中でリストと一緒に他のものをするかもしれない。

しかし、このリストはどのように解決されていますか?

interface IPartRepository : IRepository<Part> 
{ 
    // Part LoadByID(int id); comes from IRepository<Part> 
    IEnumerable<Part> GetChildren(Part part); 
} 

そして

class Part 
{ 
    ... 
    public IEnumerable<Part> GetChildren() 
    { 
     // Might manipulate this list on the way out! 
     return partRepository.GetChildren(this); 
    } 
} 

だから今、私のカタログの消費者は、リポジトリから(正確に)搭載部品に加えて、いくつかのパートにカプセル化をバイパスすることができます:リポジトリが答えであるように思えますGetChildren(part)を直接呼び出すことでロジックを構築できます。それは悪くないですか?

私は、リポジトリはPOCO'sに役立つはずですが、DTOはレイヤ間のデータ転送に適していると読んでいます。部品プロパティの多くが計算されます。たとえば、価格は複雑な価格設定ルールに基づいて計算されます。価格はリポジトリからのDTOには含まれないため、価格データをWebサービスに戻すことは、DTOがPartを消費する必要があります。

これは既に長くなっています。私の頭はどこにあるの?

答えて

2

この問題を解決するアプローチの1つは、ロジックを子パーツ自体に移動することです。すなわち、Partオブジェクトが親に​​関連付けられているときに自身を変換するようにクラスのセマンティクスを変更します。親がPart(場合、建設の際

  • Partの価格は、その親Partに依存している場合、例えば

    は、価格は、以下の時間(最低)で決定することができますその他すべての必要なデータ)が利用可能です。

  • AttachToParent(Part parentPart)の方法で、またはイベントに応答して、OnAttachedToParent(Part parentPart)となります。

  • クライアントコード(つまり、Priceプロパティの最初のアクセス時)が必要な場合。


編集:私のオリジナルの答えは(下)本当にDDDの精神ではなかったです。これは、ドメインオブジェクトを単純なコンテナにすること、多くの人がアンチパターンと考えるデザイン(Anemic Domain Modelを参照)に関連していました。

PartIPartRepositoryの間に追加の層、この問題は解決(私はそれIPartServiceを呼び出します):IPartServiceGetChildren(part)を移動し、取得するために、クライアントコードの呼び出しIPartServiceを行い、Partから削除Partオブジェクトとその子供ではなく、リポジトリに直接当たる。 PartクラスはまだChildParts(またはChildren)のプロパティを持っています。それ自体はどのように設定するのか分かりません。

明らかに、これは追加コストを課すことになります。ほとんどの場合、余分なビジネスロジックを必要としない場合は、リポジトリ呼び出しのための多くのパススルーコードを作成または生成することになります。

+0

興味深い。しかし、私は「GetChildren(part)をIPartServiceに移動してpartから削除する」と「PartクラスにはまだChildpartsプロパティがあります」と混乱します。なんらかの理由で子供がマッサージする必要がある場合はどうすればいいですか? – n8wrl

+1

マッサージをリポジトリから取得した直後に行う必要がある場合は、そのロジックを 'IPartService.GetChildren()'に入れます。子要素を任意の時刻に変更できるようにする必要がある場合は、 'IPartService.UpdateChildPartPrices(Part part) 'のような別のサービスメソッドを作ることができます(または両方とも' GetChildren'から 'UpdateChildPartPrices'を呼び出すことができます)。 –

+0

時間をとってくれてありがとう、ジェフ! – n8wrl

0

ここでの方程式の欠落部分は、Partsオブジェクトの動作と、集約をどのように使いたいかです。 n番目の再帰まで各Partの個々の子どもたちに取り組む必要がありますか、または "root" Part(親を持たない子どもたち)だけで働いていて、それは全体として子供ですか?それぞれの子のコレクションを、それは特によく自分のドメインモデルを表現していないだろうが、あなたがそれを行う可能性があり、再帰的に怠惰な負荷のように子供のようにかなり一般的に型指定されたPartsのリストが含まれていPart集約ルートを持つ

らしいです。しかし、私はまだ無限再帰が可能なところでは非常に注意が必要です。

第2の懸案事項として、DTOは、アプリケーションレイヤーとの間でデータを転送するために、レイヤー間でデータを転送するものではありません。

サービス指向アーキテクチャー(Webサービスに言及していますが、どのSOAでも構いません)を使用している場合は非常に便利です。あなたのサービスはあなたのリポジトリを照会し、余分な作業をしてから、ドメインオブジェクトをフラットなDTOにマップして、リクエストしているクライアントに返信します。 DTOはシンプルでなければならず、直列化される意図に固有のロジックとアプリケーション機能は含まれていない必要があります。

アプリケーション内のドメインオブジェクトと外部のDTOを使用します。