10

私はドメイン駆動開発に頭を悩ませようとしています。十分な基礎と理解があることを確認したいので、ここで AutoMapper などを使用することをお勧めしません。現在、私のアーキテクチャには次のものが含まれています。

ここに画像の説明を入力

  • WCF サービスは、永続性 (Entity Framework を使用) とサーバー側の検証を担当します。POCO を DTO に変換し、DTO をクライアントに転送します。

  • クライアントは DTO を受け取り、それらを POCO に変換します。POCO と DTO を変換するクラスは、サービスとクライアントの間で共有されます。

  • POCO の実装IValidatableObjectINotifyPropertyChangedおよびは、サーバーとクライアントの両方で使用されますが、データ転送には使用されません。DTO は、動作を含まない単なるプロパティ バッグです。

(1)質問 #1。このアーキテクチャはドメイン駆動設計に適していますか?
(2)質問 2。POCO にナビゲーション プロパティを含めることは適切ですか? POCO が DDD アーキテクチャにナビゲーション プロパティを含むことは、私にとって本当に間違っていると感じています。シリアル化されているかどうかにかかわらず、ナビゲーション プロパティを持つことは意味がないからです。特殊な DTO を持つ方が理にかなっています。

たとえば、これは私のアーキテクチャでの POCO/DTO の外観です。

// Enforces consistency between a POCO and DTO
public interface IExample
{
    Int32 Id { get; set; }
    String Name { get; set; }
}

// POCO
public class Example : IExample, INotifyPropertyChanged, IValidatableObject
{
    private int id;
    private string name;

    public Int32 Id {
        get { return this.id; }
        set {
            this.id = value;
            OnPropertyChanged("Id");
        }
    }

    public String Name {
        get { return this.name; }
        set {
            this.name = value;
            OnPropertyChanged("Name ");
        }
    }

    public ICollection<Example2> ChildExamples {
        get { ... }
        set { ... }
    }

    // INotifyPropertyChanged Members
    // IValidatableObject Members
}

// DTO
public class ExampleInfo : IExample
{
    public Int32 Id { get; set; }
    public String Name { get; set; }
    public ICollection<Example2Info> ChildExamples { get; set; }
}

ただし、必ずしもナビゲーション プロパティが必要なわけではなく、空の (null) オブジェクト (またはコレクション) を持つことはオブジェクト指向アーキテクチャでは非常に間違っているように思われるため、正しくないように思えます。また、深いオブジェクト階層のシリアル化と変換を行う必要がある場合もありますが、これは簡単なことではありません。特殊化された DTO のほうが理にかなっているため、シリアル化または入力が必要な場合と必要でない場合がある空のナビゲーション プロパティが常に発生する可能性があるという問題はありません。

public class ComplexInfo
{
    public Example ExampleInfo { get; set; }
    public ICollection<Example2Info> ChildExamples { get; set; }
}

これらの状況は、実際のエンタープライズ DDD スタイル アーキテクチャではどのように処理されますか? また、ここで他にどのようなアドバイスを与えることができますか?

4

4 に答える 4

10

DTOをクライアントに送信し、WCFの下のサーバー側でドメインモデルをクリーンに保つことについて、Jehofに同意します。

ナビゲーションプロパティに関して、Eric Evansがドメイン駆動設計で強調する1つのポイントは、不変条件を尊重することです。したがって、上記の例では、IdとNameがオブジェクトの存続期間中に実際に変更されるのか、それとも不変であるのかを自問してください。多くのDDDスタイルの開発者は、これらのプロパティにセッターを配置することすらしません。代わりに、コンストラクターを介してオブジェクトの不変状態を構築します。Nameが変更される可能性がある場合は、Rename(string newName)というメソッドが必要になる可能性があります。これは、とにかくそこに配置したいビジネスルールの種類があるためです。

上のレイヤーの赤い旗は、オブジェクトモデル全体がDALにあることです。アセンブリと呼ぶものは実際には大したことではありませんが、データの観点からアプリケーションを考え続ける傾向があることを示していると思います。DDDのポイントは、データや構造ではなく、ロジックと動作の観点からオブジェクトモデルを考えることです。私(および他のほとんどのDDD開発者)は、データアクセス層を集約ルートを返すリポジトリクラスと考えています。リポジトリは、ハイドレイトされたpoco / entityオブジェクトをDAL(リポジトリ)からビジネスレイヤー(および上記の例のアプリケーション/サービスレイヤークラスやWCFなど)に返す役割を果たします。EFを使用する場合は、リポジトリでDataContext呼び出しをラップし、エンティティオブジェクトを返します。

あなたの質問は実際にDDDの基本的な基礎を対象としているので、私は何度も続けることができますが、そのうちのいくつかがあります。1)EricEvansの本「DomainDrivenDesign」を読むことをお勧めします。2)DDDは複雑なビジネスソフトウェアを対象としていることに注意してください。UIフォームとDBテーブルへのデータバインディングだけである単純なCRUDアプリケーションに適用しようとしている場合、DDDアプローチが具体化するのはわかりません。これは、対処する問題が存在しないためです。ですから、それを視野に入れてください。

于 2012-11-13T14:10:17.227 に答える
3

このアーキテクチャはドメイン駆動設計に適していますか?

完全ではありません。DDD にうまく適合する、よりモダンなアーキテクチャ スタイルの説明については、hexagonal architectureを参照してください。六角形内では、ドメインがコアにあり、さまざまなコンポーネントがそれに「接続」されます。たとえば、WCF サービスは、ドメインを TCP や HTTP などの通信テクノロジに適応させるため、六角形アーキテクチャのアダプターと見なされます。通常、ドメイン上にファサードを確立し、ユース ケースを効果的に表すアプリケーション サービスがあります。このアプリケーション サービスは、WCF サービスによって参照され、HTTP 経由で機能を公開できます。残念ながら、「サービス」という用語は少し混乱する可能性があります。

POCO にナビゲーション プロパティを含めることは適切ですか?

それは適切ですが、正しい答えは、場合によるということです。あなたが述べているナビゲーション プロパティの問題の 1 つは、特定の DTO に対してシリアル化される場合とされない場合があることです。これは、クエリについて話していることを示しています。一部のクエリは、集約/エンティティ (POCO) の属性のサブセットのみを必要とするため、対応する DTO にはそれらの必要なプロパティのみが含まれます。ナビゲーション プロパティと一緒にエンティティ全体を取得するのは無駄に思えます。この問題に対処するには、遅延読み込みを使用できます。ただし、より販売可能なアプローチは、読み取りモデルを使用することですクエリ用。また、他の人が述べたように、エンティティ/集合体は、ドメインを反映している場合、ナビゲーション プロパティを確実に含めることができ、また含める必要があります。これらの「ナビゲーション」プロパティの実装方法はさまざまです。集約を複数の集約に分割した方がよい場合もあります。Vaughn Vernon による「Effective Aggregate Design 」をご覧ください。

Jehof が指摘したように、WCF サービスのクライアントは、サービスがカプセル化するドメイン エンティティ (POCO) ではなく、そのサービス自体のコントラクトのみに依存するようにする必要があります。通常、POCO は実装INotifyPropertyChangedしないでくださいIValidatableObject。これらのインターフェイスは UI の問題をサポートし、DTO または ViewModel によって処理する必要があるためです。

于 2012-11-13T20:34:35.607 に答える
1

ドメイン駆動設計は、POCOやDTOに関するものではありません。エンティティ、集約ルート、値オブジェクトについてです。データに加えて動作をカプセル化できるリッチドメインオブジェクトについて。

POCOにナビゲーションプロパティを含めることは適切ですか?

シナリオでのPOCOの目的は明確ではありませんが、POCOがドメインエンティティである場合は、ナビゲーションプロパティを含めることができます。実際、Aggregate Root(特別な種類のドメインエンティティ)のナビゲーションプロパティを使用することが、外部オブジェクトがそのAggregateに含まれるエンティティにアクセスする唯一の方法であることがよくあります。アソシエーションプロパティを介したナビゲーションは、DDDの重要な概念です。

また、DDDで推奨されるアーキテクチャは多かれ少なかれ次のようになります。

  • プレゼンテーション層(UI)
  • アプリケーション層
  • ドメインレイヤー
  • インフラストラクチャレイヤー(永続性/ DALを含む)

ここで重要なのは、単一責任の原則です。永続性、サーバー側の検証、およびDTOマッピングを同時に実行するサービスは必要ありません。デカップリングが必要です。レイヤーをより簡単に保守、拡張、および移植できるように、レイヤー間で責任を明確に分散させる必要があります。

于 2012-11-13T13:48:44.340 に答える
0

もう 1 つの提案: クライアントとサーバーの間でマッピング コード (および暗黙的にマッピング先のクラス) を共有するかどうかをよく考えてください。コードを共有することに問題はありませんが、クライアントの懸念とサーバーの懸念を混同しないように注意してください。「このプロパティはクライアントでのみ必要ですが、他のすべては同じです」という小さな妥協から始まるかもしれませんが、クライアントまたはサーバーの動作やその他の不快感を使用するかどうかをクラスに伝えるフラグで終わる可能性があります。POCO の個別の実装を持つことは、最初はコードの重複のように見えるかもしれませんが、実装をタスクに適合させることができます。だからこそ、Automapper などを使用することは理にかなっており、マッピング コードを記述する障壁が低くなります。

これを行うもう 1 つの理由 (これについても言及されています) は、DTO は API 自体ではなく、通信 API を実装する方法である必要があるためです。つまり、DTO は、WCF が SOAP API (または REST など) を実装するために存在します。ただし、クライアントは、API 仕様のみを使用して、マッピング コードに隠されたロジックを使用せずに通信層を自由に実装できる必要があります。

これにより、API が言語にとらわれないままになります。API とのやり取りを容易にするために、(いくつかの適切な言語のいずれかで) クライアント ライブラリを提供したい場合がありますが、これは必須ではありません。

于 2012-11-13T22:12:19.200 に答える