Entity Frameworkによるドメイン駆動設計の落とし穴


11

私が研究したDDDに関するチュートリアルの多くは、主に理論をカバーしています。それらはすべて基本的なコード例(Pluralsightなど)を持っています。

Webでは、EFを使用したDDDをカバーするチュートリアルを作成しようとする試みも数人います。それらをほんの少しだけ調べ始めると、それらは互いに大きく異なることにすぐに気づきます。一部の人々は、アプリを最小限に保ち、追加のレイヤー(EFの上にリポジトリなど)を導入することを避けることを推奨します。他の人々は、追加のレイヤーを決定的に生成し、多くの場合、DbContext集約ルートに注入することによってSRPに違反します。

私が意見に基づく質問をしている場合、私はひどくお詫びしますが...

実践に関しては、Entity Frameworkは最も強力で広く使用されているORMの1つです。残念ながら、DDDに関する包括的なコースは見つかりません。


重要な側面:

  • Entity Frameworkは、UoW&リポジトリ(DbSet)をすぐに使用できるようにします

  • EFでは、モデルにナビゲーションプロパティがあります

  • EFでは、すべてのモデルが常にオフで使用できますDbContext(それらはとして表されますDbSet

落とし穴:

  • あなたがすることはできません、あなたのモデルは、ナビゲーションプロパティを持っており、それが彼らとのコールを変更することができます-あなたの子供のモデルのみ集約ルートを経由して影響を受けている保証しますdbContext.SaveChanges()

  • DbContext、あなたはこのように、あなたのすべてのモデルにアクセスすることができます回避集約ルートを

  • あなたは、経由ルートオブジェクトの子へのアクセスを制限することができますModelBuilderでのOnModelCreating分野としてそれらをマークすることにより、(私はまだそれがDDDについて移動する正しい方法だとは思わないそれに加えて、これは将来的ににつながる可能性の冒険の種類何を評価するのは難しい- 非常に懐疑的

矛盾:

  • Aggregateを返すリポジトリの別のレイヤーを実装しないと、上記の落とし穴を部分的に解決することさえできません

  • リポジトリーの追加レイヤーを実装することにより、EFの組み込み機能(すべてDbSetがすでにレポです)を無視し、アプリを複雑にします。


私の結論:

私の無知を許してください、しかし上記の情報に基づいてください-それエンティティフレームワークドメイン駆動設計に適切ないか、ドメイン駆動設計が不完全時代遅れのアプローチであるかのいずれかです。

それぞれのアプローチにはメリットがあると思いますが、私は今完全に道に迷っており、EFとDDDをどのように調整するかについて少し考えていません。


私が間違っている場合-EFでDDDを実行する方法の簡単な一連の手順を詳細に説明できますか(または適切なコード例を提供できますか)。


EFがどのように機能するかについての私の理解に従って、ここで手順を詳しく説明しました。それでも、これらの手順はnavによる子供へのアクセスの問題を処理しません。プロパティまたはDbContextのDbSetsによって。
Alex Herman

回答:


8

DDDとEFは、互いにほとんどまたはまったく関係がありません。

DDDはモデリングの概念です。それは、ドメイン、ビジネス要件について考え、それらをモデル化することを意味します。特にオブジェクト指向のコンテキストでは、ビジネスの機能と機能を反映したデザインを作成することを意味します。

EFは永続化テクノロジです。主にデータとデータベースのレコードに関係しています。

これら二つは、はっきりと離婚しています。DDDの設計では、内部でなんらかの形でEFを使用できますが、2つは他の方法で相互作用してはなりません。

ドメイン駆動設計のいくつかの解釈は、実際にデータモデリングを支持しており、私はこれがあなたの質問に関するものだと思います。この解釈では、「エンティティ」と「値オブジェクト」は本質的に機能のないデータホルダーのみであり、設計はそれらがどのようなプロパティを保持し、お互いにどのような関係を持っているかに関係します。このコンテキストでは、DDDとEFの比較が考えられます。

ただし、この解釈には欠陥があり、完全に無視することを強くお勧めします。

結論:DDDとEFは相互に排他的ではなく、データモデリングではなく適切なオブジェクトモデリングを実行している限り、実際には互いに無関係です。DDDオブジェクトは、EFアーティファクトであってはなりません。たとえば、DDDエンティティはEF「エンティティ」であってなりませ。一部のビジネス関連機能の内部では、DDD設計はEFをいくつかの関連データオブジェクトと共に使用する場合がありますが、それらは常にビジネス関連の動作指向のインターフェースの下に隠されている必要があります。


1
EFは時間の節約にすぎません。変更の追跡と集計の永続化は、EFが既に多くのことを支援しています。残念ながら、現在、構成レベルでアグリゲートの形状を定義する方法はありません。
Pavel Voronin

6

EFは、生のADO.NETよりもわずかに強く型付けされたデータアクセスライブラリであるものとして扱います。生のDataSetまたはDataTableを使用してドメインをモデル化するのと同じように、EFエンティティクラスを使用してドメインをモデル化することはお勧めしません。

私はEFがデータベースアクセスとドメインモデリングの間のショートカットとして販売されていることを理解していますが、このアプローチは2つの大きく無関係な問題に対処するため、本質的に欠陥があります。.NETには、クラスに完全に関連のない処理(.NET Remotingなど)を実行させる他の試みがありましたが、うまくいきませんでした。

POCOクラスを使用してDDDを実行し、データベーススキーマに設計を推進させないでください。EFをリポジトリ/永続化レイヤー内に保持し、EFエンティティが外部に漏洩しないようにします。


5

Entity Frameworkは、UoW&リポジトリ(DbSet)をすぐに使用できるようにします

番号。

Entity Frameworkの抽象化は、DDDではなくORMを念頭に置いて構築されました。DbSetEntity Frameworkのどのバージョンの抽象化も、DDDリポジトリの単純DbContextさにはほど遠いです。言うまでもなく、UnitOfWorkよりも多くのことを公​​開しています。

DbSet<TEntity>DDDで必要のないEF Core 2.1の要約の要素の完全ではないリストを次に示します。

  • Attach(TEntity) とそのすべての兄弟
  • Find(Object[])
  • Update(TEntity) とそのすべての兄弟
  • 実装 IQueryable

それらとの不要な依存関係に沿ってドラッグすることに加えて、これらは通常非常に単純なコレクション動作を公開するリポジトリの意図を覆い隠します。さらに、リークの多い抽象化は、開発者がEFに過度に結合しようとする絶え間ない誘惑であり、懸念の分離への脅威です。

結論:これらの脂肪をすっきりとした合理化された概念にラップし、何を推測するか、つまり追加のクラスを導入する必要があります。

EFとDDDを使用してできることの比較的健全な例(いくつかの見解は議論の余地がありますが):https : //kalele.io/blog-posts/modeling-aggregates-with-ddd-and-entity-framework/

その他は明らかに追加のレイヤーを生成しており、多くの場合、DbContextを集約ルートに挿入することでSRPに違反しています。

この文の2つの部分の間の関係は本当にわかりません。アプローチに関係なく、DDDにはアプリケーションサービスと呼ばれるものがあり、そこで作業ユニット/リポジトリ(またはDbContext)を操作します。集合根にはありません。

教育を受けたトレードオフである場合、これは有効なアプローチとなる可能性がありますが、最近の反リポジトリー「エンティティフレームワークミニマリズム」の傾向は妄想的です。フレームワークをそのまますぐにベストプラクティスに準拠させるために何もしなかったのがEF作成者である場合に、Entity Frameworkで発生する摩擦のDDDパターンのせいです。コードの安全性と保守性の点で問題が発生し、フレームワークと密接に結びついています。


2

矛盾:

Aggregateを返すリポジトリーの別のレイヤーを実装しないと、上記の落とし穴を部分的に解決することさえできません

リポジトリの追加レイヤーを実装することで、EFの組み込み機能を無視し(すべてのDbSetはすでにリポジトリである)、アプリを過度に複雑にします。

私は、すべての集合体が独自のDBContextを取得し、集合体に必要なものだけをマッピングするアプローチを使用しました。これはJulie Lermanにも説明されていると思います。

これは非常にうまくいきましたが、コンセプトをエンティティにリンクしたくない、もっと興味深いモデルには不十分かもしれません。



DBContext Per Aggregateアプローチの利点はありますか?これは、EFでDDDを実装するデフォルトの方法ですか?
Alex Herman

Julie Lermanは、境界コンテキストごとのDbContextを意味していませんでしたか?
Mvision

0

考えられる解決策を共有したいだけです。

  1. サービスレイヤーでEFプロジェクトを直接参照しないようにする

  2. 追加のリポジトリレイヤーを作成します(EFプロジェクトを使用し、集約ルートを返します)

  3. Service Layerプロジェクトのリポジトリレイヤーを参照する

建築

  • UI

  • コントローラー層

  • サービス層

  • リポジトリ層

  • エンティティフレームワーク

  • コアプロジェクト(EFモデルを含む)


このアプローチで私が見る落とし穴:

  • リポジトリがEFモデルツリーではなく集約ルートを返す場合(たとえば、マップされたオブジェクトを返す)-変更を追跡するEFの機能が失われます

  • 集約ルートがEFモデルである場合- 対処できない場合でも、そのナビゲーションプロパティすべて利用可能ですDbContext(サービスレイヤーではEFプロジェクトを参照しません)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.