このテーマについて結論を出すためにウェブ上で (そして本で) 何時間も費やした後、多くの人々の視点を調べ、賛否両論を比較しようとするさまざまな側面を調べた後、いくつかの重要な質問を投稿することにしました。私よりも賢い人が答えてくれることを願っています:)
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 に基づいて、もう適用できません。とにかくそれらを実行してから元に戻しますか? それは正しく聞こえません