3

EF Code FirstまたはNHibernateで使用され、リポジトリレイヤーから返される次の2つの単純な永続化クラスを使用してブログアプリケーションを作成するとします。

public class PostPersistence
{
   public int Id { get; set; }
   public string Text { get; set; }
   public IList<LikePersistence> Likes { get; set; }
}

public class LikePersistence
{
    public int Id { get; set; }
    //... some other properties
}

永続性モデルをドメインモデルにマッピングするためのクリーンな方法がわかりません。ドメインモデルのインターフェースを次のようにしたいと思いPostます。

public interface IPost
{
   int Id { get; }
   string Text { get; set; }
   public IEnumerable<ILike> Likes { get; }
   void Like();
}

さて、その下の実装はどのように見えるでしょうか?多分このようなもの:

public class Post : IPost
{
   private readonly PostPersistence _postPersistence;
   private readonly INotificationService _notificationService;

   public int Id 
   { 
       get { return _postPersistence.Id }
   }

   public string Text 
   { 
       get { return _postPersistence.Text; }
       set { _postPersistence.Text = value; }
   }

   public IEnumerable<ILike> Likes
   {
       //this seems really out of place
       return _postPersistence.Likes.Select(likePersistence => new Like(likePersistence ));
   }

   public Post(PostPersistence postPersistence, INotificationService notificationService)
   {
       _postPersistence = postPersistence;
       _notificationService = notificationService;
   }

   public void Like()
   {
       _postPersistence.Likes.Add(new LikePersistence());
       _notificationService.NotifyPostLiked(Id);
   }
}

私はDDDについて読むことに時間を費やしましたが、ほとんどの例は理論的であるか、ドメイン層で同じORMクラスを使用していました。実際、ドメインモデルはORMクラスの単なるラッパーであり、ドメイン中心のアプローチではないように思われるため、私のソリューションは本当に醜いようです。また、IEnumerable<ILike> LikesLINQ to SQLのメリットがないため、実装方法が気になります。より透過的な永続性の実装でドメインオブジェクトを作成するための他の(具体的な!)オプションは何ですか?

4

2 に答える 2

2

DDD における永続性の目標の 1 つは、永続性を無視することです。それはあなたがある程度努力しているように見えるものです。コード サンプルで見られる問題の 1 つは、エンティティがインターフェイスを実装し、リポジトリとサービスを参照していることです。DDD では、エンティティは、それ自体の単なる抽象化であり、リポジトリまたはサービスにインスタンスの依存関係を持つインターフェイスを実装するべきではありません。エンティティの特定の動作にサービスが必要な場合は、そのサービスを対応するメソッドに直接渡します。それ以外の場合、サービスおよびリポジトリとのすべてのやり取りは、エンティティの外部で行う必要があります。通常、アプリケーション サービスで。アプリケーション サービスは、ドメイン エンティティで動作を呼び出すために、リポジトリとサービスの間で調整を行います。その結果、エンティティは サービスまたはリポジトリを直接参照する必要はありません。それらが持つのは、その状態を変更し、その整合性を維持する何らかの状態と動作だけです。次に、ORM の仕事は、この状態をリレーショナル データベースのテーブルにマップすることです。NHibernate などの ORM を使用すると、比較的高度な持続性無知

アップデート

INotificationService をパラメーターとして使用してメソッドを公開したくありません。このサービスは内部である必要があり、上のレイヤーはそれについて知る必要がないためです。

クラスの現在の実装では、PostクラスINotificationServiceと同じかそれ以上の可視性があります。がインフラストラクチャ層に実装されている場合はINotificationService、すでに十分な可視性が必要です。現代のアーキテクチャにおける階層化の概要については、六角形のアーキテクチャをご覧ください。

補足として、通知に関連する機能は、多くの場合、ドメイン イベントのハンドラーに配置できます。これは、高度なデカップリングを達成するための強力な手法です。

また、DTO とドメイン クラスが分離されている場合、ドメイン オブジェクトがその基になる DTO を認識していない場合、持続性同期の問題をどのように解決しますか? 変更を追跡する方法

DTO と対応するドメイン クラスが存在する理由は大きく異なります。DTO の目的は、システム境界を越えてデータを運ぶことです。DTO は、ドメイン オブジェクトと 1 対 1 で対応していません。ドメイン オブジェクトの一部またはドメイン オブジェクトへの変更を表すことができます。変更を追跡する 1 つの方法は、含まれる変更について DTO を明示的にすることです。たとえば、 を編集できる UI 画面があるとしますPost。その画面は、行われたすべての変更をキャプチャし、それらの変更をコマンド (DTO) でサービスに送信できます。サービスは適切なPostエンティティをロードし、コマンドで指定された変更を適用します。

于 2012-12-05T16:06:40.783 に答える
0

もう少し調査を行い、すべてのオプションを確認して、完全な DDD 実装に行くのが本当に面倒かどうかを判断する必要があると思います。私はここ数日間そこに行ったので、私の経験をお話しします.

最初の EF コードは非常に有望ですが、かなりの問題があります。この Entity Framework と Domain Driven Designのエントリがここにあります。EF を使用すると、別の「永続化」クラスを作成しなくても、EF によってドメイン モデルを永続化できます。POCO (プレーン オールド オブジェクト) を使用して単純なアプリケーションを起動して実行することはできますが、私が言ったように、まだ完全には成熟していません。

LINQ to SQL を使用する場合、最も一般的な方法は、"データ転送オブジェクト" をビジネス オブジェクトに手動でマップすることです。大規模なアプリケーションの場合、手動で行うのは難しい場合があるため、Automapper などのツールを確認してください。または、次のようなビジネス オブジェクトで DTO を単純にラップすることもできます。

  public class Post
   {
      PostPersistence Post { get; set;}
      public IList<LikePersistence> Likes { get; set; }
       .....
   }

NHibernate: よくわかりません。長い間使用していません。

これに対する私の感覚 (これは単なる意見であり、私が間違っている可能性があります) は、常に妥協をしなければならず、完璧な解決策を見つけることはできないということです。EFにあと数年与えれば、そこにたどり着くかもしれません。DTO を DDD オブジェクトにマップするアプローチがおそらく最も柔軟だと思うので、自動マッピング ツールを探すのは時間の価値があるかもしれません。シンプルに保ちたい場合は、必要に応じて DTO のシンプルなラッパーを使用するのが私のお気に入りです。

于 2012-12-05T02:04:59.920 に答える