【ITニュース解説】Can executable business logic be designed in a Service instead of an Entity in DDD?
2025年09月22日に「Dev.to」が公開したITニュース「Can executable business logic be designed in a Service instead of an Entity in DDD?」について初心者にもわかりやすく解説しています。
ITニュース概要
DDDではエンティティがビジネスロジックを持つことが多い。だが、ロジックをサービスに移し、エンティティがデータのみになる設計は許容されるか?この「貧血症エンティティ」化でも、DDDの核となる概念は保てるのか、という問いかけだ。
ITニュース解説
ドメイン駆動設計(DDD)は、ソフトウェア開発において、特に複雑なビジネス領域(ドメイン)を扱う際に強力な手法として知られている。その目的は、開発者とビジネス担当者が共通の理解を持って、現実世界の業務や概念をソフトウェアモデルに正確に反映させることだ。
DDDの根幹をなす概念の一つが「ユビキタス言語」である。これは、プロジェクトに関わる全員が共通で使う言葉や専門用語を指し、コード、ドキュメント、会話のすべてで一貫して使用されるべきだ。これにより、ビジネスの意図がソフトウェアに正確に反映され、誤解が最小限に抑えられる。次に「境界づけられたコンテキスト」という概念がある。これは、特定のドメインモデルが有効な明確な境界を定義するもので、異なる文脈では同じ言葉でも異なる意味を持つことがあるため、それぞれのモデルが適用される範囲を区切ることで複雑さを管理する。例えば、「顧客」という概念は、営業部門と経理部門ではその意味合いが異なる可能性がある。このような場合、それぞれの文脈で独立した「顧客」モデルを定義し、それらのコンテキスト間で明確な「分離」を設けることで、変更の影響範囲を限定し、システムの独立性と保守性を高めるのだ。
DDDにおける主要な設計要素には、「エンティティ」「値オブジェクト」「サービス」がある。 「エンティティ」は、一意の識別子(ID)を持ち、時間の経過とともに状態が変化するオブジェクトを指す。例えば、オンラインストアにおける「顧客」や「注文」などがこれに該当する。エンティティはIDによって区別され、属性値が変わっても同じオブジェクトとして扱われる。DDDの伝統的な考え方では、エンティティは単にデータを持つだけでなく、そのデータに関連する「振る舞い」、すなわちビジネスロジックも内包することが求められる。例えば、「注文」エンティティであれば、「商品の追加」や「注文の確定」といった操作自体をエンティティ自身が実行する責任を持つ。
「値オブジェクト」は、識別子を持たず、その属性値の組み合わせによって等価性が決まるオブジェクトである。例えば、「住所」や「金額」などが値オブジェクトの例だ。これらは不変であり、一度作成されたらその値は変更されない。もし値が変わる場合は、新しい値オブジェクトを生成して置き換える。これにより、データの整合性が保たれやすくなる。
「サービス」は、特定の操作や処理を実行するが、状態を持たない、あるいは永続的な状態を持たないオブジェクトである。サービスは、複数のエンティティや値オブジェクトを調整し、特定のビジネスプロセスを実行する役割を担う。例えば、「注文処理サービス」は、「顧客」エンティティや「商品」エンティティを用いて「注文」エンティティを作成し、在庫を更新するといった一連の操作を調整するかもしれない。サービスは通常、複数のエンティティにまたがる複雑なビジネスロジックや、エンティティのライフサイクルに属さない操作を扱うために用いられる。
今回のニュース記事の問いかけの中心は、「ビジネスロジックをエンティティではなくサービスに設計することが許容できるか」という点である。DDDの伝統的な考え方では、エンティティが自身のデータに対する振る舞いを持つことで、オブジェクト指向設計の「カプセル化」を最大限に活かし、現実世界のオブジェクトをソフトウェア内でより忠実に表現することが重視される。これにより、エンティティの状態が外部から不適切に操作されることを防ぎ、整合性を保ちやすくなる。
しかし、記事では、ビジネスロジックをサービス層に配置し、エンティティがデータ保持のみに特化する「アネミックエンティティ」(貧血症エンティティ)となるケースについて議論している。アネミックエンティティとは、IDと属性を持つものの、それらの属性を操作するビジネスロジックを持たず、単なるデータ構造として振る舞うエンティティのことだ。これは、伝統的なDDDの考え方とは対立するとされ、なぜなら、エンティティが振る舞いを持たないことで、関連するビジネスロジックがサービス層に散らばり、コードの見通しが悪くなったり、ドメインモデルの表現力が低下したりする可能性があるからだ。ビジネスルールの変更が複数のサービスに影響を与えることになり、保守性が損なわれる恐れもある。
それでも記事の筆者は、「エンティティがアネミックになったとしても、それが引き続き製品の側面の一部として、そしてコンテキストやユビキタス言語の一部としてアイデンティティを維持するならば、DDDの主要なコンセプトは維持されるように見える」という「妥協」の可能性を示唆している。これは、厳密なオブジェクト指向の原則に固執することよりも、DDDが本来目指す「複雑なドメインの共通理解と管理」が達成されているかどうかをより重視する見方である。
つまり、開発チームがユビキタス言語を適切に用い、境界づけられたコンテキストを明確に定義し、各コンテキストの分離を保っているならば、たとえ個々のエンティティが振る舞いをあまり持たず、ビジネスロジックの多くがサービス層に集約されたとしても、システム全体の理解度や保守性が損なわれないのであれば、それは許容される選択肢となり得るのか、という問いかけがなされているのだ。
現実の開発現場では、フレームワークの制約、チームメンバーのスキルセット、開発期間など、さまざまな要因によって、理想的なDDDの設計を常に適用することが難しい場合がある。このような状況下で、DDDの核となる理念(ユビキタス言語による共通理解、境界づけられたコンテキストによる複雑さの管理)を維持しつつ、具体的な実装の詳細において柔軟なアプローチを取ることの是非を問うているのがこの記事の核心である。
この議論は、DDDを実践する上で常に課題となる点だ。エンティティに振る舞いを持たせることでドメインの表現力を高めるのか、それともサービスにロジックを集約することで特定の状況下での開発効率や見通しを優先するのか。最終的に重要なのは、その設計が複雑なドメインの理解を助け、ソフトウェアがビジネス要件を正確に満たし、長期的な保守性を確保できるかどうかである。アネミックエンティティが良いか悪いかという二元論ではなく、その設計がDDDの目標達成にどのように貢献するか、あるいは阻害するかを総合的に判断することが求められる。