10

殴打されて死んだと思われる方は、あらかじめお詫び申し上げます。私はここ数時間、ここSOで多くの優れた投稿を検索して読んだばかりですが、それでも混乱しています。

私の混乱の原因は、DTOとDDDおよびリポジトリです。POCOドメインオブジェクトにスマートを持たせ、リポジトリから取得したいと思います。しかし、それを機能させるには、いくつかのカプセル化ルールに違反する必要があるようであり、DTOを彼らの頭に向けることができるようです。

簡単な例を次に示します。カタログアプリケーションでは、パーツは他の多くのパーツを含むパッケージである可能性があります。したがって、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を提供する必要があるが、DTOは「レイヤー間」でデータを転送するのに適していることを読みました。多くの部品プロパティが計算されます。たとえば、価格は複雑な価格設定ルールに基づいて計算されます。価格はリポジトリからのDTOにも含まれません。したがって、価格データをWebサービスに戻すには、DTOがパーツを消費する必要があります。その逆ではないようです。

これはすでに長くなりすぎています。頭を緩めたところはどこですか?

4

2 に答える 2

2

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

たとえば、 a の価格がPartその親に依存している場合、価格Partは次の時点で (少なくとも) 決定できます。

  • 構築時に、親Part(およびその他の必要なすべてのデータ) が利用可能な場合。

  • メソッド内またはイベントへの応答、AttachToParent(Part parentPart)つまりOnAttachedToParent(Part parentPart).

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


編集:私の最初の答え(以下)は、実際にはDDDの精神ではありませんでした。これには、ドメイン オブジェクトを単純なコンテナにする必要があり、多くの人がアンチパターンと見なす設計でした ( Anemic Domain Modelを参照)。

Partとの間の追加レイヤーIPartRepository(ここでは と呼びますIPartService) がこの問題を解決します: に移動GetChildren(part)してIPartServiceから削除し、リポジトリに直接アクセスするのではなく、Partクライアント コードを呼び出しIPartServiceてオブジェクトとその子を取得します。クラスにはまだPart(または) プロパティがあります。それ自体を設定する方法がわからないだけです。PartChildPartsChildren

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

于 2009-07-17T14:52:45.900 に答える
0

ここで式に欠けているのは、Partsオブジェクトの動作と、集計をどのように処理するかです。n 番目の再帰のそれぞれの個々の子で作業する必要がありPartますか、それとも「ルート」Part(つまり、親のないもの) だけで作業し、それは全体としての子ですか?

Part子としてかなり一般的に型指定されたリストを含む集約ルートを持つことはParts、ドメイン モデルを特にうまく表現していないように見えますが、それを実行して、各子コレクションを再帰的に遅延ロードすることができます。ただし、無限再帰が可能な場合は、まだ細心の注意を払っています。

2 番目の懸念については、DTO は、アプリケーション レイヤーとの間でデータを転送する場合ほど、レイヤー間でデータを転送するためのものではありません。

サービス指向アーキテクチャを使用している場合、これらは非常に便利です (Web サービスについて言及していますが、それは任意の SOA である可能性があります)。サービスはリポジトリにクエリを実行し、追加の作業を行ってから、ドメイン オブジェクトをフラットな DTO にマップして、要求元のクライアントに送り返します。DTO はシンプルで、シリアル化を意図した特定のロジックやアプリケーション機能を含まない必要があります。

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

于 2009-08-04T15:45:59.737 に答える