ドメインモデル貧血症は、ドメインオブジェクトに検証、計算、ルールなどのビジネス ロジックがほとんどまたはまったく含まれていないプログラミングのアンチパターンとして説明されます。ビジネス ロジックはプログラム自体のアーキテクチャに組み込まれているため、リファクタリングとメンテナンスが困難になり、時間がかかります。
概要
このアンチパターンは、この実践をアンチパターンとみなしたマーティン・ファウラーによって最初に説明されました[1]。彼は次のように述べています。
このアンチパターンの根本的な恐ろしさは、それがオブジェクト指向設計の基本的な考え方、つまりデータとプロセスを結合するという考え方に非常に反している点です。貧血症ドメイン モデルは単なる手続き型設計であり、まさに私のようなオブジェクト偏執狂がSmalltalkの初期の頃から戦ってきた類のものです。さらに悪いことに、貧血症オブジェクトが実際のオブジェクトであると考える人が多く、オブジェクト指向設計の本質を完全に見失っています。
ドメイン貧血症の設計では、ビジネス ロジックは通常、ドメイン オブジェクトの状態を変換する別のクラスに実装されます。Fowler は、このような外部クラスをトランザクション スクリプトと呼んでいます。このパターンは、 Javaアプリケーションで一般的なアプローチであり、おそらくEJBのエンティティ Beanの初期バージョンなどのテクノロジによって促進されたものです。[1]また、このようなオブジェクトが「ビジネス エンティティ」のカテゴリに分類される (ただし、ビジネス エンティティには動作を含めることもできます) 3 層サービス アプリケーション アーキテクチャに従う.NETアプリケーションでも促進されています。[2]
Fowler 氏はトランザクション スクリプト パターンを次のように説明しています。
ほとんどのビジネス アプリケーションは、一連のトランザクションとして考えることができます。あるトランザクションは、ある情報を特定の方法で整理して表示し、別のトランザクションはそれを変更します。クライアント システムとサーバー システム間の各インタラクションには、一定量のロジックが含まれます。場合によっては、これはデータベースに情報を表示するだけの単純なものになることがあります。また、検証や計算の多くの手順を伴うこともあります。トランザクション スクリプトは、このすべてのロジックを主に 1 つのプロシージャとして整理し、データベースに直接呼び出しを行うか、薄いデータベース ラッパーを介して呼び出します。各トランザクションには独自のトランザクション スクリプトがありますが、共通のサブタスクはサブプロシージャに分割できます。[3]
ファウラーは著書「エンタープライズ アプリケーション アーキテクチャのパターン」の中で、トランザクション スクリプト パターンは多くの単純なビジネス アプリケーションに適しており、複雑な OO データベース マッピング レイヤーが不要になる可能性があると述べています。
ドメイン モデル貧血症は、メッセージング/パイプライン アーキテクチャやSOAP / REST APIなど、動作が伝わらない、または伝わらない傾向があるサービス指向アーキテクチャの影響を受けるシステムで発生する可能性があります。COM+ やリモート処理などのアーキテクチャでは動作が許可されますが、Web ではますます切断されたステートレス アーキテクチャが好まれるようになっています。
批判
このソフトウェア設計パターンをアンチパターンと見なすべきかどうかについては、次のような利点も認める人が多いため、批判もあります。
- ロジックとデータを明確に分離します。[4]
- シンプルなアプリケーションに適しています。
- ステートレス ロジックが生成され、スケールアウトが容易になります。
- 複雑な OO データベース マッピング レイヤーの必要性を回避します。
- 特定のコンストラクタやプロパティの配置順序ではなく、ダムプロパティを期待するマッピングおよびインジェクションフレームワークとの互換性が向上します。[4]
よくある批判は、貧血ドメイン モデルを使用するとSOLID原則 に従いやすくなるという考えです。
「『S』は単一責任原則を指し、クラスは1つのことだけをうまく行うべきであることを示しています(...)」[5]
しかし、ロバート・C・マーティンによれば、これはその原則の誤解です。
「SOLID のすべての原則の中で、単一責任原則 (SRP) は最も理解されていないかもしれません。それは、特に不適切な名前が付けられているためでしょう。プログラマーは、その名前を聞くと、すべてのモジュールが 1 つのことだけを行うべきであると考えがちです。誤解しないでください。そのような原則は存在します。関数は 1 つのことだけを行うべきです。この原則は、大規模な関数を小さな関数にリファクタリングするときに使用します。最も低いレベルで使用します。しかし、これは SOLID の原則の 1 つではなく、SRP でもありません。(...) SRP の最終バージョンは、モジュールは 1 つのアクターに対してのみ責任を負うべきである、というものです。[6]」
負債
貧血症ドメイン モデルを使用すると、プログラマーが考慮しなければならない特定の責任が発生します。
- ロジックは、真にオブジェクト指向的な方法で実装することはできません。
- カプセル化と情報隠蔽の原則に違反しています。
- ドメイン モデルに配置されているロジックを格納するための別のビジネス レイヤーが必要です。また、検証および変更ロジックが外部のどこか (おそらく複数の場所) に配置されているため、ドメイン モデルのオブジェクトはいかなる時点でも正確性を保証できないことも意味します。
- オブジェクト モデルの異なるコンシューマー間でドメイン ロジックを共有する場合は、サービス レイヤーが必要です。
- モデルの表現力が低下します。
例
貧血ドメイン モデルには、次のようなコード ( C#で記述) が含まれます。このコード自体は、この場合、高さまたは幅が 0 または負の値にならないことや、四角形の面積に関する要件がどこか別の場所で必要であることなど、ビジネス上の懸念事項を実装していません。つまり、これらの機能は、プログラムの「ビジネス」側ではなく、アーキテクチャ内の隠れたどこか別の場所で実装されていることになります。
クラスRectangle { public int Height { get ; set ; } public int Width { get ; set ; } }
上記のクラスを貧血症を起こさずに書き直すと、次のようになります。ビジネス上の懸念事項はドメイン オブジェクトで処理されるようになり、アーキテクチャはよりドメインに依存しなくなります。これにより、アーキテクチャ内の他の場所で妥当性チェックを実装しなくても、プログラムはオブジェクトに関する特定の属性が真であると想定できます。
クラスRectangle { public int Height { get ; private set ; } public int Width { get ; private set ; }
パブリックRectangle ( int高さ、int幅) { SetHeight (高さ); SetWidth (幅); }
パブリックvoid SetHeight ( int height ) { if ( height <= 0 ) { throw new ArgumentOutOfRangeException ( nameof ( height )); }
高さ=高さ; }
パブリックvoid SetWidth ( int width ) { if ( width <= 0 ) { throw new ArgumentOutOfRangeException ( nameof ( width )); }
幅=幅; }
パブリックint CalculateArea () {高さ*幅を返します; } }
参照
- 昔ながらのJavaオブジェクト
- ドメイン駆動設計
- GRASP情報エキスパート、貧血症ドメインモデルは、情報エキスパート原則を適用しなかった典型的な結果です。つまり、データを含む同じクラスに責任を割り当てようとすることで、貧血症ドメインモデルを回避できます。
参考文献
- ^ ab "Bliki: AnemicDomainModel"より。
- ^ 「.NET のアプリケーション アーキテクチャ: アプリケーションとサービスの設計」。2013 年 1 月 10 日時点のオリジナルよりアーカイブ。2013 年 2 月 13 日閲覧。
- ^ 「P of EAA: トランザクション スクリプト」。
- ^ ab 「The Anaemic Domain Model is no Anti-Pattern, it's a SOLID design – SAPM: Course Blog」。2014 年 2 月 4 日。
- ^ 「The Anaemic Domain Model is no Anti-Pattern, it's a SOLID design – SAPM: Course Blog」2014 年 2 月 4 日。2022年 9 月 14 日閲覧。
- ^ Martin, Robert C. (2018). クリーンアーキテクチャ:ソフトウェア構造と設計の職人ガイド。ボストン。ISBN 978-0-13-449432-6. OCLC 1003645626.
{{cite book}}: CS1 メンテナンス: 場所が見つかりません 発行者 (リンク)
外部リンク
- Martin Fowlerによる貧血ドメイン モデル
- 3層サービスアプリケーション
- .NET のアプリケーション アーキテクチャ: アプリケーションとサービスの設計
- 貧血モデルがなぜ良いデザインと考えられるかについての記事
- ASP.NET でクリーンなコードを書く
- ドメインモデル貧血症を回避する方法
