問題タブ [anemic-domain-model]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
architecture - この「貧血」モデルは許容できる設計ですか?
私は最初に、現在の設計でドメインモデルを実現しようとしているのではないことを言いたいと思います。
そうは言っても、私は現在、次のようなアーキテクチャを構築しています。
私はEricEvanのDDDの本を読んでいて、 Greg YoungのDDDプロジェクトが失敗する7つの理由を見てきました。そして、貧血モデルを恐れています。私はDDDを処方していませんが、非常に類似したものを前後にマッピングし続けるのが面倒になるほど多くのレイヤーを作成したくありません。
しかし、私が行うセットアップを持っている理由は2つあります。変更のしやすさとあいまいさ
- 変更のしやすさ:パブリックオブジェクトがサービスを介して公開されており、UIとビジネスオブジェクトを内部で使用している場合、既存のAPIを壊すことなく自由に変更を加えることができます。しかし、おそらく1つのDTOを使用して、DTOが逸脱し始めた場合にリファクタリングすることができますか?
- あいまいさ:パブリックオブジェクトを公開することはできますが、完全なオブジェクトとその実装が内部にある場合は公開できません。これは安全な製品である必要があるので、私はその準備をしています。しかし、多分また、後でそれをリファクタリングすることができますか?
だから、私の質問はこれです:私の現在のモデルは意味がありますか、それとも後で問題を求めていますか?これらのオブジェクトは主にDTOであるため、問題ありませんか?Evanの本でさえ、彼は、このモデルが異なるサーバーに分散されるように計画されている場合は問題ないことを示唆していますか?それで、UI、サービス、およびDBレイヤーを異なるサーバー上に配置できるようにすることを計画しているので、この理由だけでレイヤー化は問題ありません(現在は必要ないため、現在は使用されていません)。
オーバーアーキテクチャを認識しようとしているだけですが、同時にアンダーアーキテクチャを回避しようとしています.....それで、このモデル構造は私の現在の実装にとって良いのか悪いのか?
lucene - Lucene を使用した DTO から POCO へ
データ取得用の検索サーバーとして Lucene を使用しています。
これに伴い、私は準備ができていなかった特定の複雑さが生じます。そのうちの少なくとも 1 つは、オブジェクト間の関係の管理です。
ドメイン オブジェクト用のクリーンでシンプルな POCO を作成したいと考えています。これらの POCO には、UI に必要な関連オブジェクトが含まれますが、他のフィールドは含まれません (これらの関係を定義する ID、UI では必要のない他のさまざまなフィールド)。
つまり、Lucene の Hits コレクションを UI フレンドリーな POCO に直接変換することはできず、少なくとも関連オブジェクトの ID を含むクラスの中間セットが必要です (同じインデックスまたは他のインデックスに格納されます)。これらの DTO オブジェクトを呼び出すのをためらっていますが、簡単にするために、そのように呼びます。
したがって、次のように機能すると想定しています。
- Lucene でクエリを実行 -> ヒット コレクション
- ヒットを繰り返す -> DTO コレクション
- DTO コレクション -> [関連オブジェクトを取得するサービス、POCO を作成] -> POCO
- 光沢のあるシンプルな POCO を使用して UI をレンダリングする
そうすることで私が恐れているのは、Anemic Domain Model ( http://www.martinfowler.com/bliki/AnemicDomainModel.html ) になってしまうことです。
これは有効な懸念ですか、それとも私は正しい道を進んでいますか?
entity-framework - ルールの形でビジネスロジックを使用して貧血ドメインモデルを回避する方法
一連のルールに基づいて更新する必要のあるフィールドを持つ単純なEntityFrameworkでサポートされたドメインオブジェクトを持つシステムを設計しています-これらのルールを段階的に(アジャイルスタイルで)実装したいので、EFを使用しているので懐疑的です各ルールをドメインオブジェクトに配置する方法について。ただし、「手続き型コード」を記述したり、貧血ドメインモデルを使用したりすることは避けたいと思います。これもすべてテスト可能である必要があります。
例として、オブジェクトは次のとおりです。
「給与が100,000を超え、_eligibleForPensionがfalseの場合、_eligibleForPensionをtrueに設定する」、「_pensionがtrueの場合、_eligibleForPensionをtrueに設定する」などのルールを作成する必要があります。
そのようなルールは約20ありますが、それらをEmployeeクラスに実装するか、EmployeeRulesクラスのようなものに実装するかについてアドバイスを求めています。私の最初の考えは、「Rule」から継承するルールごとに個別のクラスを作成し、Visitorパターンを使用して、各ルールをEmployeeクラスに適用することでしたが、これを行うには、すべてのフィールドをルールに公開する必要があります。気分が悪い。Employeeクラスに各ルールを設定することも、まったく正しくないと思います。これはどのように実装されますか?
2番目の懸念は、実際のEmployeesがDBにバックアップされたEntity Frameworkエンティティであるため、これらの「エンティティ」にロジックを追加することに満足していないことです。特に、各ルールの単体テスト用にオブジェクトをモックする必要がある場合はそうです。同じオブジェクトでテストしているルールがある場合、どうすればそれらをモックできますか?
ルールを適用する前に、AutoMapperを使用してより単純なドメインオブジェクトに変換することを考えていましたが、フィールドの更新を自分で管理する必要があります。これについてもアドバイスはありますか?
java - 既存の (サードパーティ) データモデル (Java) を使用したドメイン駆動開発
最初に、ソフトウェアを開発するための私の標準的なアプローチは、おそらく多くの開発者にとって典型的なものであると言いたいです...動作が豊富であるが状態を持たないサービスと、状態のみを持ち、何も持たないオブジェクト (Bean) があります。動作 (これは通常、Anemic Domain Model と呼ばれると思います)。
新しいプロジェクトでドメイン駆動設計 (DDD) アプローチを試すことにしましたが、いくつかの問題があり、本当に困っています。
私の組織が使用している既存のサードパーティのデータベースがあります (そして、それはビジネスに密接に結びついており、これについて私にできることはありません: サードパーティが変更した場合にこれがどのように問題につながる可能性があるかについて言及するコメントは望みません)。データモデル...知っています!!)。データを表す休止状態のエンティティを作成しましたが、これを DDD の原則 (つまり、データ アクセスをカプセル化するリッチ ドメイン モデル) に準拠した内部モデル表現に変換する方法がわかりません。
この種の問題にはパターンがあるはずですが、見つけるのが難しいと感じています。これは、私がおそらく間違った方法で何かをしている (つまり、通常のアプローチ方法ではない) と信じるように導きます。
私の現在の戦略は次のとおりです。
- 休止状態のエンティティの中から主要なエンティティを特定し、これらを関連する値オブジェクトと一緒にパッケージ化しようとします (これは非常に困難でした。データから始めてドメインを作成しているためだと思います...アプローチ方法に関する提案はありますか?これも大歓迎です)
- 特定したパッケージごとに、エンティティを管理するためのリポジトリを作成しました
- 各リポジトリ (例: StudentHibernateRepository) で、必要な hibernate エンティティを取得し、それらをプロキシ クラスにラップします。
- 各プロキシ クラスで、ラップされた hibernate エンティティをデータ ソースとして使用するために通過するビジネス ルールを追加します (ここでも、コードの動作をリッチにしようとしています)。
誰かが似たようなことをした経験がある場合は、経験/パターンを共有してください. また、私がとった戦略を振り返っていただけると助かります。
乾杯、
Jラブ
domain-driven-design - ドメイン モデルを貧血と分類する基準は何ですか?
これまでのところ、ドメイン モデルを貧血とタグ付けするための客観的な基準を説明しているブログ投稿や記事に出くわしたことはありません。貧血ドメインモデルの客観的な基準を設定することは間違いなく役立つと思います.
数年前、私はドメイン モデルを設計しました。データベースにはいくつかのテーブルがありました(約7)。コードでまったく同じ数のクラスを作成しました。これらのクラスごとにリポジトリ パターンを実装しました。今日は間違いなく貧血ドメインモデルだったと思います。オブジェクト指向のドメイン モデルを設計する機会がありましたが、設計したドメイン モデルは本質的にリレーショナルでした。その経験から、私が定義した 1 つの基準は、オブジェクト モデルがリレーショナル モデルと 1 対 1 でマッピングされている場合、それは貧血ドメイン モデルの兆候である可能性があるということです。
貧血ドメインモデルを指している可能性のある他の基準はありますか?
ありがとう。
oop - RDM 対 ADM (またしても) または中間点はどこにあるのでしょうか?
このテーマについて結論を出すためにウェブ上で (そして本で) 何時間も費やした後、多くの人々の視点を調べ、賛否両論を比較しようとするさまざまな側面を調べた後、いくつかの重要な質問を投稿することにしました。私よりも賢い人が答えてくれることを願っています:)
Martin Fowler の ADM (Anemic Domain Model と彼は呼んでいます) に関する記事や本を読み、Eric Evan の DDD (Domain Driven Design) についても知っています。彼らは非常に立派で経験豊富な建築家であり、これらすべての知識を著書や記事にまとめる並外れた仕事をしてきましたが (すべての印刷媒体はそうであるため、これを行うのはほとんど不可能であることを私は知っています)、彼らの例を以下に示します。通常は非常に明確で、概念を説明するのには問題ありませんが、残念ながら実際に使用するのは困難です。
ここでは、(RDM / ADM+TS(Service)) でのあなたのオプションに非常に興味があるいくつかのケースを簡単に説明します。IoC コンテナーが配線を行っていると仮定しましょう (ほとんど関係ありませんが)。
ケース I/1:
TASK: 注文する
ADM+TS:
要件:
Order オブジェクト - データ (set+get) (DTO のような「データ バッグ」)
OrderService - 操作 (エンティティ オブジェクトに対する TS のような操作)
RDM:
要件:
注文オブジェクト - データと機能 (リッチ)
ケース I/2:
TASK: 注文してからメールを送る
ADM+TS
要件:
Order オブジェクト - データ (set+get) (DTO のような「データ バッグ」)
OrderService - 操作 (エンティティ オブジェクトに対する TS のような操作)
EmailService - 電子メールを送信する
(オプション)注文、メール送信
コメント:
解決策:
a. a.既存の OrderService を使用し、メール送信を追加します。この場合、OrderService は EmailService に依存します
。懸念事項を、IoC のサービスと一緒に配線できるデコレータに分割し、これが必要かどうかに基づいてオンデマンドを使用します
RDM:
要件:
オブジェクトの注文 - データと機能 (リッチ)
? EmailService - メールを送信するには
? EventHandler - イベントをキャッチする
コメント:
この場合、人々は通常、次のことを推奨します
。「依存関係をドメイン層に注入する」: ドメイン層が非常に重くなり、あちこちに依存関係がいっぱいになります。
b. 「place(...) 呼び出しと一緒にサービスを渡す」: これにより、関数のシグネチャが常に変更され、依存関係がどんどん増えていきます。
c. 「重要な操作が完了したというイベントを発生させる」: 最も強力な RDM 支持者でさえ、持続性はドメイン モデルに直接あるべきではないと言っています。そのため、完了する前にメールを送信する場合があります。メールは失敗する可能性があるのでどちらにしても完璧ではありませんが、ここでは実際に注文することが主な操作であり、メールを送信することは単なる通知であり、それを繰り返すことができ、さらに画面に表示されると思います通知など。ここで要点がわかりました。実際には、注文は通知メールを送信できるかどうかに依存していませんが、注文の永続化に失敗した場合、メールを送信したくないことは間違いありません。しかし、それが永続化されているリポジトリでそのようなイベントを発生させ、
ケース I/3:
タスク: 注文は一括で行うことができます。すべての注文を記載した 1 つの通知メールのみを送信したいと考えています (これらが同じ注文の商品であることにコメントしないでください。これは一例です)。
ADM+TS
要件:
Order オブジェクト - データ (set+get) (DTO のような「データ バッグ」)
OrderService - 操作 (エンティティ オブジェクトに対する TS のような操作)
BulkOrderService
-
OrderService に依存します (非装飾)集約された電子メールの送信を EmailService に依存するには
コメント:
装飾された OrderService を使用する代わりに、(装飾された) BulkOrderService を使用します。
RDM:
要件:
オブジェクトの注文 - データと機能 (リッチ)
? EmailService - メールを送信するには
? EventHandler - イベントをキャッチする
コメント: 私たちのドメイン オブジェクトは少し複雑になりました。.bulkPlace() を配置することはできません。同じコンテキストで複数の注文を配置したいので、ロジックが 1 層上に存在する必要があるためです。たとえば、コントローラー レベルで、各注文で各 place() を呼び出します
。(「注入された依存関係」) ここで送信される電子メールをどのように回避しますか? ここで、.placeWithEmailAndAnyOtherDependency.. と .placeWithout...? が必要です。ドメインオブジェクトを公平に装飾することはできません
b. (「サービスを渡す」)ここで、サービスの代わりに null を渡すと、メールが送信されない可能性があります(しかし、それは危険なようです)
c. ("イベントを発生させる") これは問題です。メール送信をこのイベントに結び付けたので、.place() 呼び出しを再利用したいのですが、大量注文であっても、何らかの方法で切り離さない限り、複数のメールが送信されます。 (リポジトリを実際に装飾することもできません)
現在、これらの問題のいくつかはおそらくデコレーターの代わりに AOP で解決できますが、それでもハックのように感じます。
ケース I/4:
タスク: スケジューラーから定期的な大量注文を「スケジュール」できるようにしたいが、この機能を Web サイトに直接保持したいので、複数のエントリ ポイントがあります。(または、Web クライアントと同様にコンソール クライアントを使用する必要があると言うことができます。ポイントは、いずれにせよ直接ではなく、Web コントローラーが仕事をしないということです)
ADM+TS
要件 (変更なし):
Order オブジェクト - データ (セット + 取得) (DTO のような「データ バッグ」)
OrderService - 操作 (エンティティ オブジェクトに対する TS のような操作)
BulkOrderService
- OrderService に依存します (非装飾)
電子メール
BulkOrderServiceEmailDecorator - 集約された電子メールの送信を EmailService に依存する
コメント: 装飾された OrderService を使用する代わりに、(装飾された) BulkOrderService を使用します - 基本的に何も変わりません
RDM:
要件:
オブジェクトの注文 - データと機能 (リッチ)
? EmailService - メールを送信するには
? EventHandler - イベントをキャッチする
コメント: I/2 で何をしたかにもよりますが、I/3 と同じ問題がまだ適用されますが、その上、コントローラーを使用して注文をループすることはできません。 TS であり、ADM+TS で得られる同様の階層化アーキテクチャに戻ります
したがって、私の主な問題は、このような単純な問題に対して、RDMで明確で適切な解決策を見つけることができなかったことです。読んでグーグルで検索した後でも、1つのことを解決するのに適していますが、出血していますADM+TS ソリューションは、それらをより柔軟に扱うことができます。(DTOが必要ないという事実は言うまでもありません.ADMは本質的にDTOであり、イベントをビューに渡すことができるため、変換は必要ありません)
ケース I/2 および /3 を RDM で (漸進的に) 適切に処理する方法について意見がある場合は、コメントを残してください。 、または少なくとも最後の 3 つは、1 は実際には問題ではないため)! あなたが納得のいく答えを持っているものだけではありません(タスクの半分など)
ありがとう
アップデート: いくつかの答えを見て、私はおそらく、このエクササイズの有名な騎士団とは別の「実体」を選ぶべきだったでしょう (私は単に馴染みのあるものを選びたかっただけです)。とにかく、補足として、ケース I/2、I/3、I/4 は初期要件ではなく、有機的に進化したものだと想像してみてください。これらの要件は段階的に追加されました。最初は注文があればいつでもメールを送信するように言われましたが、これらを何らかの方法で組み合わせると、I/3 が大量注文にヒットしたときに問題が発生します。電子メールをメッセージバスに置いたばかりで、まだ送信されていない場合でも、一括で何をしますか? 次に、メッセージをバスに置いてから、それを削除/クリーンアップしますか? または、I/2 に基づく他のアクションをトリガーする必要がありますが、I/3 に基づいて、もう適用できません。とにかくそれらを実行してから元に戻しますか? それは正しく聞こえません
.net - ドメイン オブジェクト - 「スマート オブジェクト」と POCO
スマートオブジェクトによって、プロパティが変更された場合に元のプロパティ値を知っているドメインオブジェクトを考慮します。通常、スマート オブジェクトには基本クラスがあり、GetPropertyValue/SetPropertyValue メソッドを使用してプロパティを実装します。一方、POCO オブジェクトは通常、基本クラスを持たず、単純なプロパティを実装します。
私はスマート オブジェクトが好きです。これらの便利な機能をすべて BaseDomainObject に簡単に追加して、すべての派生ドメイン クラスに含めることができます。
- 共通プロパティ (ID、ステータスなど)
- オブジェクトの状態の追跡 (新規、変更済み、未変更)
- すべてのプロパティは、プロパティの変更時にイベントを発生させます (INotifyProperyChanged の実装)
- 派生クラスは自動的にシリアライズ可能になります (ただし、これが役立つことはめったにありません)。
- クローン/同期/IsPropertyDirty...
一方、POCO は非常に単純で、どの基本クラスにも依存しません。
今日、私はここで多くのPOCOを賞賛しています。
- ネットワーク経由で送信できます (通常は JSON として Web ブラウザーに送信されます)。
- それは純粋です
一方、上記の理由は次の理由から誤謬であると思います。
- DTO は電信送金用であり、ドメイン オブジェクトではありません。ドメイン オブジェクトが JSON にシリアル化されたときに失われたデータをカプセル化する動作。
- この純度の追求は、ロジックもスマートなものも何も付いていない、さらに貧血なドメインモデルの追求のようなものです。
この悲しいことに、私はまだそのPOCOが好きで、私を悩ませています. あなたの意見は何ですか?
c# - 豊富なドメイン モデル。抗貧血ドメインモデル
thisやthisのような多くの議論は、RICH DOMAIN MODELに関連しています。
amenic については、1 と 3 のように 2 つの強力な理由があります。
ここで、製品が在庫に存在することを検証し、存在しない場合は例外をスローする必要があることを確認する必要があるとしましょう。
ISomeRepository
質問があります: オブジェクトがサービスのように依存する必要がない場合は、次のようにできますか?
次のように呼び出します。
design-patterns - EAA の P におけるドメイン モデルとサービス層パターン
エンタープライズ アプリケーション アーキテクチャのパターンで、Martin Fowler は、ドメイン ロジックを編成するための 2 つのパターン、ドメイン モデルとサービス層について説明しています。ドメイン モデル パターンは「純粋な OOP」アプローチであり、モデル (おそらく ORM を使用してデータベースから検索されるオブジェクト) にビジネス ロジックが含まれます (ただし、おそらく別のクラスのロジックに委譲するだけです)。
サービス層パターンはドメイン モデル パターンに似ていますが、その前に実行可能なビジネス オペレーションを含む薄い層があります。MVC では、コントローラーは主にサービス層と対話します。適切に設計された MVC Web アプリケーションのほとんどは、このパターンを使用していると思います。
さて、私の質問に。Martin は、ドメイン モデル アプローチはよりオブジェクト指向のアプローチであり、したがってより優れていると示唆しています。私の経験では、実際に実装するのは非常に困難です (不可能を参照)。
上の最初の図の例を見てください。2 つの「エンティティ」Contract
とがありProduct
ます。これらは、マッパーを使用してデータベースに永続化されます。例では、 がありRecognitionStrategy
ます。Martin は、実際のビジネス ロジックを含むこの戦略に委任するためのメソッドをエンティティ自体に配置します。contract.calculateRecognitions
クライアントは、またはを使用してこの計算を実行しますcontract.recognizedRevenue(someDate)
。同様の設計を実装する場合、通常、クライアント インターフェイスをstrategy.calculateRecognitions(contract)
およびとして記述しますstrategy.recognizedRevenue(contract, someDate)
。これにより、戦略と契約を調整するためにサービス層が必要になります。使用される具体的な戦略がサービスに注入されます。
マーティンのアプローチは、デザインの観点からは間違いなく魅力的ですが、セットアップを回避する作業ははるかに困難です。
- a をインスタンス化するときに戦略を渡すのは
Product
面倒です。使用する具体的なサービスでカリー化されたファクトリを介してを作成する必要がありますProduct
。これにより、作成時にエンティティに渡されます。 - データベース アクセスに対するきめ細かい制御ができません。ORM の設定によっては、 への
Contract
委任がProduct
ごとにクエリを実行する場合がありますProduct
。Product
マッパー (または ORM) に s を貪欲にロードすることは、 をロードするContract
が を呼び出すつもりがない場合、熱心すぎるかもしれませんcontract.calculateRecognitions()
。私のアプローチでは、サービスがデータベース抽象化レイヤーの知識を持っているため、よりきめ細かい制御が可能になりますが、エンティティはそうすべきではありません。
ここに列挙していない問題点が実際にはもっとあると確信しています。
Martin のアプローチには、純粋なデータ モデル パターンを使用するよう説得する具体的な利点は何ですか?