DDD-貧血ドメインモデルはアンチパターンですか?リッチドメインモデルを使用しているのでしょうか。[閉まっている]


11

貧血ドメインモデルは、明らかにオブジェクト指向の原則などに反するため、EvansとFowlerによって以前から批判されていました。DDDコミュニティは、この発言と明確に一致しています。

しかし、近年、これはアンチパターンではなく、SOLIDの原則に従う例であると主張する意見の相違があります。

私は長年、Spring Frameworkを使用して作業してきました。すべての会社のすべてのプロジェクトには、貧血モデル(JPAエンティティ)で動作するリポジトリを使用して、ビジネスロジックを含むサービスレイヤーが常にあります。さらに、ほとんどのサンプルは、Springの公式のサンプルでさえ、この作業方法を示しています。

私の質問は次のとおりです。貧血ドメインモデルは依然としてアンチパターンと見なされていますか?私たち全員が(DDDに関して)間違ったことをしたことがありますか?リッチドメインモデルを持つことはSOLIDの原則に違反すると思いませんか?


2
貧血ドメインモデルは依然としてアンチパターンと見なされていますか?」一部では、はい。私自身も含めて、ほとんどの場合、それをコードを記述する好ましい方法と見なしていますが、RDMが適している場合は、それを使用してください。したがって、これを純粋に意見に基づくものとして閉じるように投票します。
David Arno

1
これは、ディスカッション/ディベートフォーラムにとって素晴らしい質問です。しかし、現在のところ信頼できる回答はありません。 議論するだけでなく、答えられる質問を好む。
VoiceOfUnreason 2017年

回答:


9

ADMは、マイクロサービスなどの分散サービスのソリューションに適したパターンです。今日のWebベースのビジネスケースの多くに適合します。

Order Domainオブジェクトがあるかどうかを検討します。OOPアプローチでは、Order.Purchase()Order.Cancel()などを追加します。これは、メモリに注文を保持し、同じインスタンスに対して複数のことを行うデスクトップアプリでうまく機能します。

しかし、1つのこと、つまり注文のリストにアクセスして順番に購入するプログラム、または注文のリストを取得して順番にキャンセルするプログラムを使用する分散システムがある場合、同じオブジェクトに両方のメソッドがあると、センス。2つのドメインまたはバインドされたコンテキストが必要です。

PurchaseSystemOrder.Purchase()

そして

CancelSystemOrder.Cancel();

これらのオブジェクトが共有する唯一のものは、プロパティのデータ構造です。

マイクロサービスをどんどん追加していくと、何十種類もの注文ができてしまいます。これらのすべてのシステムによって処理されている同じ概念的な順序であっても、ドメインオブジェクトとして注文について話すことはもはや意味がありません。

データだけをカプセル化し、それに応じてサービスの名前を変更する、貧血モデルであるOrderを使用する方がはるかに理にかなっています。

PurchaseService.Purchase(Order order)

これでOrderについて再び話し合うことができ、現在デプロイされている他のサービスに影響を与えることなく、処理するために考えている新しいサービスを追加できます。

FowlerとCoはモノリスシステムのバックグラウンドから来ています。彼らの世界では、ADMアプローチは、これらの個別のサービスすべてがメモリ内でインスタンス化され、OrderDTOが渡されて変更される単一のアプリを意味します。これは、メソッドをリッチなOrderモデルに配置するよりもはるかに悪いでしょう。

しかし、分散システムには多くのプログラムがあり、それぞれが単一のOrderメソッドのみを必要とし、それを複数のオーダーで実行し、それぞれをロードし、メソッドを実行してから破棄します。必要なのは、単一のサービスとデータオブジェクトのストリームだけです。

すべてのメソッドの要件と依存関係を心配して1つのメソッドを呼び出し、その後すぐにオブジェクトを破棄することで、リッチモデルを完全に生成しても意味がありません。

さらに、メソッドの1つを変更するには、すべての分散コンポーネントを更新する必要があります。これらのコンポーネントはすべて、ロジックがリッチモデルに依存しているためです。

コードベースに必要のないもののためのスペースがない


4
制限付きのコンテキストの概念により、DDDは特にマイクロサービスに特に適していると思うので、反対票を投じました。あなたの答えの問題は、注文の概念とクラスが各マイクロサービスで同じになることですが、それは必要でも正確でもないと思います。
RibaldEddie 2017年

異論はありません。PurchaseServiceCashRegisterを呼び出してドメイン言語の一部にする場合、ADMはDDDになる可能性があります
Ewan

詳しく説明できますか?ADMとDDDがSOLID J2EEまたは.NET C#MVC EFコードベースにあるとき、私はいつもYMMVだと思っていました。
RibaldEddie 2017年

つまり、境界コンテキストOrder、PurchaseSystemOrder.Purchase()は、CashRegister.Purchase(Order order)とほぼ同じコードであり、ドメイン言語の名前が変更されただけです。リッチドメインモデルとは、同じクラスにPurchaseメソッドとCancelメソッドの両方を持つことを意味します。
ユアン

1
@RibaldEddie、 "javaScript、the good parts"本の厚さの脈絡で、私はこの画像をマイクロサービスの実装にDDDを使用することに対する(完全に深刻ではない)議論として提供します;)
David Arno

3

SOLIDとDDDは互いに直交しているため、実際には互いに異なる方向に進んでいます。同じコードベースに一緒に存在でき、おそらく存在する必要があるため、一方が他方の除外に慣れていると言ってはいけません。

貧血ドメインモデルがアンチパターンになるのは、問題のあるドメインに多くの動作があり、コピー貼り付けされたロジックや依存関係がたくさんある何百ものサービスメソッドがあり、サービスレイヤーメソッドが他のサービスレイヤーメソッドを呼び出して何かを実行する必要がある場合のみです。

DDDは、境界のあるコンテキストの概念により、マイクロサービスの優れたパラダイムです。

インフラストラクチャコードをドメインの一部として見る誘惑に注意してください。インフラストラクチャコードは、自分で作成したものではないもの、またはサードパーティのシステムと相互作用するフレームワークまたはライブラリに結合されたものです。データベース接続、SMTPメーラー、ORMライブラリ、アプリケーションサーバーランタイムなど、すべてがインフラストラクチャであり、回避できる場合はドメインに含めたり、依存したりしないでください。

SOLIDの原則は、より優れたOOPコードを作成するために使用できる一連の汎用OOP概念です。それらを使用して、優れたDDDコードベースを作成できます。


ドメインからのインフラストラクチャコードの分離について。これまでのところ、私はJPAエンティティを私のドメインと見なし、次のアプリケーションレイヤーを備えています:コントローラー->サービス->リポジトリ->ドメイン(JPAエンティティ)。あなたのポイントに従ってそれをモデリングする正しい(または正しい)方法は何ですか?次のようなもの:コントローラ->リッチモデル-> x?トランザクション性をどのように、どこで処理しますか?そして、JPAマッピングはどうですか?分離したJPAエンティティを使用して、リッチモデルを複製する必要はありませんか?
2017年

JPAエンティティは、古いJavaオブジェクトです。マッピングはインフラストラクチャの一部ですが、クラス自体は必須ではありません。それをインフラストラクチャの一部として扱うことを選択した場合は、ドメインエンティティを作成するためにファクトリまたはリポジトリで使用されるデータ転送オブジェクトと見なす必要があります。
RibaldEddie 2017年

1

リッチドメインは、うまくやればいいです。ないときの悪夢。貧血ドメインは常に悪いです。しかし、お馴染みの快適な種類の悪い。

貧弱なドメインだけが必要な場合は、汎用言語を選択するときに間違った言語を選択します。第4世代の言語は、特定の用途に特化しています。貧血で十分であれば、それらを使用することで生活が楽になります。

多くのフレームワークは、Javaジョブとしてそのジョブをアドバタイズできなくなるまで、言語スペースに侵入します。これはJava / Springジョブです。彼らがやっていることは、あなたを彼らに依存させることのほかに、汎用言語を第4世代言語の卑劣な形に変えることです。

それはベストプラクティスですか、それともアンチパターンですか?まあ、あなたは上司がコードベースで作業するために人々を雇うことができるかどうかを気にするだけです。したがって、私たちが汎用言語を使って人を雇うふりをする必要がある場合は、そうします。

それで大丈夫なら、それで結構です。確かにあなただけではありません。

しかし、そうであるべきだと私に言わないでください。それ以上に私のために何かをしていると言わないでください。私はそれなしで生きる方法を知っています。私はそれを押し出す方法を知っているので、それに依存するものはほんの少しです。戦うのが難しいからといって、私に譲ってすべてを引き継がせるように頼んでいるなら、そうだと思う。

私のコードベースには、必要のないもののためのスペースがありません。

SOLIDと他の設計原則に関しては、貧血の領域でもそれらに大部分従うことができます。それらに従わないと、別の種類の問題が発生します。


私はあなたの答えに感謝し、SpringやJPA-Hibernateなどの一部のフレームワークがJavaランドスケープを征服したことに完全に同意します。ただし、Java(JEE)がまったく対処しなかった、または誤って処理した一連の優れた実践と簡素化が提供されていることも否定できません。経験、純粋なDDDアプリ(Rich Domain Modelsを使用)を使用するのに最適なプラットフォーム/言語/フレームワークは何ですか?あなたが私が物事をうまくやりたいと言うように、悪い習慣に適合しないでください。
共依存2017年

ここではリソースの推奨を行いません。しかし、フレームワークを扱う適切なインフラストラクチャレイヤーは、好きな種類を使用できることを意味すると思います。それらをライブラリのように扱ってください。それらの知識をドメインの外に保ちます。また、魔法に頼らないでください。自分では作れなかったものを使いたいという衝動に抵抗します。いつかあなたがする必要があるかもしれません。
candied_orange 2017年

元のポイントに戻ります。SOLIDの原理についてはどうですか?リッチドメインモデルは、多くの責任、永続性(JPA)、ビジネスロジック(トランザクション性に対処する必要がある)などを想定しています。一方、貧血モデルは、ビジネスロジックを処理する分離されたサービスの永続性のみを考慮します。テストも簡単です。それで何がそんなに悪いのですか?
共依存2017年

主なことは、意味上のニーズではなくシステムのニーズに基づいて設計の選択を始めることです。その微妙で無視しやすいコストは明らかではなく、修正を正当化するのは困難です。要するに、送電線は投票所ではなく埋められるべきだと主張するようなものです。人々が安っぽい選択肢に慣れると、それが変わる可能性は低いでしょう。ハリケーンが力をノックアウトするときでも。
candied_orange 2017年

1
「豊かなドメインは上手くいけばいい。そうでなければ悪夢だ」というあなたの主張に対する疑いの恩恵をあなたに与えるつもりでした。多分私はそれがうまくいくのを見たことがなかったかもしれません、しかしあなたは「貧血ドメインは常に悪い」というナンセンスな主張をします。あなたの答えを価値のないものにしている意見のあるナンセンス。-1
デビッドアルノ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.