貧血ドメインモデル
2003年11月25日
これは、かなり長い間存在しているにもかかわらず、最近特に勢いを増しているように見えるアンチパターンの1つです。このことについてエリック・エヴァンスと話していたところ、二人とも人気が高まっているように感じていることに気づきました。適切なドメインモデルの強力な支持者としては、これは良いことではありません。
貧血ドメインモデルの基本的な兆候は、一見すると本物のように見えることです。ドメイン空間の名詞にちなんで名付けられたオブジェクトが多数存在し、これらのオブジェクトは、真のドメインモデルが持つ豊かな関係と構造でつながっています。問題は、動作を見たときに、これらのオブジェクトにはほとんど動作がなく、ゲッターとセッターの単なる袋にすぎないことに気づくことです。実際、これらのモデルには、ドメインオブジェクトにドメインロジックを配置しないという設計ルールが付いていることがよくあります。代わりに、すべてのドメインロジックをキャプチャし、すべての計算を実行し、モデルオブジェクトを結果で更新するサービスオブジェクトのセットがあります。これらのサービスは、ドメインモデルの上に存在し、データをドメインモデルに使用します。
このアンチパターンの根本的な恐ろしさは、データとプロセスを組み合わせるというオブジェクト指向設計の基本的な考え方と正反対であるということです。貧血ドメインモデルは実際には手続き型の設計であり、私(とエリック)のようなオブジェクト原理主義者がSmalltalkでの初期の頃から戦ってきた種類のものです。さらに悪いことに、多くの人が貧血オブジェクトを実際のオブジェクトであると考えているため、オブジェクト指向設計の要点を完全に見逃しています。
さて、オブジェクト指向の純粋主義は非常に優れていますが、この貧血に対するより根本的な議論が必要であることを私は認識しています。本質的に、貧血ドメインモデルの問題は、ドメインモデルのすべてのコストを負担しながら、メリットを何ももたらさないことです。主なコストは、データベースへのマッピングのぎこちなさであり、通常、O/Rマッピングの全体のレイヤーになります。これは、複雑なロジックを整理するために強力なOOテクニックを使用する場合に価値があります。ただし、すべての動作をサービスに引き出すことで、本質的にトランザクションスクリプトになってしまい、ドメインモデルがもたらす可能性のある利点が失われます。P of EAAで議論したように、ドメインモデルが常に最適なツールであるとは限りません。
また、動作をドメインオブジェクトに入れることは、永続性やプレゼンテーションの責任などのものからドメインロジックを分離するためにレイヤーを使用するという確実なアプローチと矛盾してはならないことを強調しておく価値があります。ドメインオブジェクトにあるべきロジックは、ドメインロジック(検証、計算、ビジネスルールなど、何でも好きなように呼んでください)です。(データソースまたはプレゼンテーションロジックをドメインオブジェクトに入れるという議論をする場合もありますが、それは私の貧血の見方とは無関係です。)
このすべてにおける混乱の1つの原因は、多くのOOエキスパートが、サービスレイヤーを形成するために、ドメインモデルの上に手続き型サービスのレイヤーを配置することを推奨していることです。しかし、これはドメインモデルから動作をなくすための議論ではありません。実際、サービスレイヤーの支持者は、動作が豊富なドメインモデルと組み合わせてサービスレイヤーを使用します。
エリック・エヴァンスの優れた書籍ドメイン駆動設計には、これらのレイヤーについて次のように書かれています。
アプリケーションレイヤー(サービスレイヤーの彼の名前):ソフトウェアが実行すべきジョブを定義し、表現力豊かなドメインオブジェクトに問題を解決するように指示します。このレイヤーが担当するタスクは、ビジネスにとって意味があるか、他のシステムのアプリケーションレイヤーとの対話に必要なものです。このレイヤーは薄く保たれています。ビジネスルールや知識は含まれていませんが、タスクを調整し、次のレイヤーにあるドメインオブジェクトのコラボレーションに作業を委任するだけです。ビジネス状況を反映する状態はありませんが、ユーザーまたはプログラムのタスクの進行状況を反映する状態を持つことができます。
ドメインレイヤー(またはモデルレイヤー):ビジネスの概念、ビジネス状況に関する情報、およびビジネスルールを表す責任があります。ビジネス状況を反映する状態は、それを保存する技術的な詳細はインフラストラクチャに委任されているにもかかわらず、ここで制御および使用されます。このレイヤーはビジネスソフトウェアの核心です。
ここでの重要な点は、サービスレイヤーが薄いことです。すべてのキーロジックはドメインレイヤーにあります。彼はサービスのパターンでこの点を繰り返しています。
さて、より一般的な間違いは、適切なオブジェクトに動作を適合させることをあまりにも簡単に諦め、徐々に手続き型プログラミングに向かって滑り落ちることです。
このアンチパターンがなぜこんなに一般的なのかわかりません。特にデータバックグラウンドを持つ場合、適切なドメインモデルを実際に使用したことがない多くの人が原因ではないかと疑っています。J2EEのエンティティBeanなど、それを助長するテクノロジーもあります。これが、私がPOJOドメインモデルを好む理由の1つです。
一般的に、サービスに存在する動作が多いほど、ドメインモデルの利点を奪う可能性が高くなります。すべてのロジックがサービスにある場合、あなたは自分自身を完全に奪ってしまっています。