メインコンテンツに移動

ドメインモデルとは?リッチドメインモデルと貧血ドメインモデルの違いを徹底解説

業務システム開発では、単に画面やデータベースを作るだけでなく、業務上のルールや判断基準をどのようにソフトウェア上で表現するかが非常に重要です。注文、請求、在庫、契約、承認、ユーザー権限など、業務には多くのルールが存在します。これらのルールを適切に設計できていないと、機能追加のたびに条件分岐が増え、ロジックが分散し、保守が難しいシステムになってしまいます。

このような業務ルールやドメイン知識を整理し、ソフトウェア上で表現するための考え方がドメインモデルです。ドメインモデルは、ビジネス領域の概念やルールをコード上のモデルとして表現し、システムの中心に据える設計手法です。特に複雑な業務システムでは、ドメインモデルの設計品質が、システム全体の保守性や拡張性に大きく影響します。

ドメインモデルを考えるうえでよく議論されるのが、リッチドメインモデルと貧血ドメインモデルの違いです。リッチドメインモデルは、データと振る舞いを同じモデル内に持たせる設計スタイルです。一方、貧血ドメインモデルは、モデルをデータ入れ物として扱い、業務ロジックをサービス層など外部に置く設計スタイルです。どちらにもメリットとデメリットがあり、プロジェクトの規模や業務ルールの複雑さによって適切な選択は変わります。

本記事では、ドメインの意味、ドメインモデルの役割、ドメイン駆動設計との関係、リッチドメインモデルと貧血ドメインモデルの特徴、メリット・デメリット、ビジネスロジックの配置、リポジトリやドメインサービスとの関係、実務での使い分けまで体系的に解説します。

1. ドメインとは?

ドメインとは、ソフトウェアが対象とする業務領域や問題領域のことです。たとえば、ECサイトであれば商品、注文、決済、配送、在庫管理などがドメインに含まれます。銀行システムであれば口座、取引、残高、振込、与信などがドメインになります。つまり、ドメインとは、システムが解決しようとしている現実世界の業務や知識のまとまりです。

ドメインを正しく理解せずに開発を進めると、表面的な機能は作れても、業務の本質に合わない設計になりやすくなります。業務ルールが複雑なシステムほど、ドメイン知識をコードへ正しく反映することが重要です。ドメインを理解することは、単なる仕様理解ではなく、システムが扱うビジネスの意味を理解することでもあります。

主な特徴

項目内容
日本語業務領域・問題領域
意味システムが扱うビジネス上の対象
注文、在庫、契約、請求、ユーザー管理
重要性業務ルールを正しく設計するために必要
関連概念ドメインモデル、ドメイン駆動設計

1.1 ビジネス領域

ビジネス領域とは、企業や組織が実際に行っている業務の範囲を指します。たとえば、販売管理システムであれば、見積、受注、出荷、請求、入金確認などがビジネス領域に含まれます。これらは単なるデータ項目ではなく、業務上の意味やルールを持っています。

ソフトウェア設計では、このビジネス領域を正しく分解し、どの概念が重要で、どのルールが守られるべきかを整理する必要があります。ビジネス領域を十分に理解せずにデータベースや画面から設計を始めると、後から業務ルールの追加や修正が難しくなることがあります。

1.2 ドメイン知識の重要性

ドメイン知識とは、対象業務に関する専門知識やルールのことです。たとえば、ECサイトでは「在庫がない商品は購入できない」「注文確定後は支払い状態を管理する」「キャンセル可能な期間が決まっている」といったルールがドメイン知識になります。

ドメイン知識は、システムの価値を決める重要な要素です。単にデータを保存するだけであれば一般的な実装でも対応できますが、業務固有のルールを正しく扱うには、ドメイン知識を設計に反映する必要があります。ドメインモデルは、この知識をコード上で表現するための中心的な手段になります。

1.3 ソフトウェア設計との関係

ソフトウェア設計では、ドメインをどのようにモデル化するかによって、システムの保守性や拡張性が大きく変わります。ドメインの概念が適切に表現されていれば、コードを読むだけで業務ルールを理解しやすくなります。反対に、ドメイン知識が画面処理やサービス層、データベース処理に散らばっていると、変更時の影響範囲が分かりにくくなります。

特に長期運用される業務システムでは、ドメインの理解とモデル化が重要です。業務ルールは時間とともに変化するため、その変化に対応しやすい設計を作る必要があります。ドメインモデルは、そのための土台になります。

2. ドメインモデルとは?

ドメインモデルとは、業務領域に存在する概念、ルール、振る舞いをソフトウェア上で表現したモデルです。単なるデータ構造ではなく、ビジネス上の意味を持つオブジェクトとして設計されます。たとえば、注文、顧客、商品、契約、請求などをコード上のモデルとして表現し、それぞれに必要な業務ルールを持たせます。

ドメインモデルの目的は、業務ルールをコードの中心に置き、システム全体の一貫性を保つことです。業務ルールが分散していると、同じルールが複数箇所に重複したり、画面ごとに異なる判断が行われたりする可能性があります。ドメインモデルを適切に設計することで、業務の知識を一箇所に集約しやすくなります。

主な特徴

項目内容
日本語ドメインモデル
目的業務ルールをコード上で表現する
対象エンティティ、値オブジェクト、ドメインサービスなど
強みドメイン知識を集約できる
関連手法ドメイン駆動設計、オブジェクト指向設計

2.1 業務ルールの表現

ドメインモデルは、業務ルールを表現するための設計手法です。たとえば、「注文は在庫がある場合のみ確定できる」「会員ランクによって割引率が変わる」「請求済みの注文は変更できない」といったルールを、ドメインモデルの振る舞いとして実装します。

このように業務ルールをモデル内に表現すると、ルールの所在が明確になります。画面やアプリケーションサービスに条件分岐を散らばらせるのではなく、業務の中心となるモデルにルールを持たせることで、保守しやすい設計になります。

2.2 オブジェクト指向との関係

ドメインモデルは、オブジェクト指向設計と相性が良い考え方です。オブジェクト指向では、データと振る舞いを同じオブジェクトにまとめ、責務を持たせます。ドメインモデルも同様に、単なるデータではなく、業務上の意味と振る舞いを持つオブジェクトとして設計されます。

たとえば、注文オブジェクトが「合計金額を計算する」「注文を確定する」「キャンセル可能か判定する」といった振る舞いを持つ場合、そのモデルは業務ルールを自然に表現できます。これは、リッチドメインモデルの考え方にもつながります。

2.3 ドメインモデルが必要な理由

ドメインモデルが必要な理由は、業務ルールを整理し、変更に強い設計を作るためです。業務ルールがサービス層や画面処理に分散していると、仕様変更時に複数箇所を修正する必要があり、修正漏れや不整合が発生しやすくなります。

ドメインモデルを中心に設計すれば、業務ルールの配置が明確になります。複雑な業務システムほど、ドメインモデルを適切に設計することで、長期的な保守性と拡張性を高めることができます。

3. ドメインモデルの役割

ドメインモデルの役割は、ビジネスルールを整理し、システム内で一貫した形で扱えるようにすることです。業務システムでは、同じルールが複数の画面や機能で利用されることがあります。ドメインモデルがないと、同じ条件判定が各所に重複し、変更時に不整合が起きやすくなります。

ドメインモデルは、開発者と業務担当者の共通理解を形成するためにも重要です。業務上の言葉や概念をコード上のモデルとして表現することで、仕様と実装の距離を縮められます。これはドメイン駆動設計におけるユビキタス言語の考え方とも関係します。

3.1 ビジネスルールの整理

ドメインモデルは、複雑なビジネスルールを整理する役割を持ちます。たとえば、注文処理には、在庫確認、価格計算、割引適用、支払い状態、配送状態など多くのルールが関わります。これらを画面やサービス層に散らばらせると、全体像が見えにくくなります。

ドメインモデルに業務ルールを集約することで、どの概念がどの責務を持つのかが明確になります。結果として、コードの可読性が高まり、仕様変更にも対応しやすくなります。

3.2 保守性向上

ドメインモデルを適切に設計すると、保守性が向上します。業務ルールがモデル内にまとまっていれば、仕様変更が発生したときに修正箇所を見つけやすくなります。また、同じルールを複数箇所に書かずに済むため、修正漏れのリスクも下がります。

保守性の高いシステムでは、変更の影響範囲が明確です。ドメインモデルは、業務ルールの責務を明確にすることで、長期的な保守コストを下げる効果があります。

3.3 共通理解の形成

ドメインモデルは、開発チームと業務担当者の共通理解を形成するためにも役立ちます。モデル名、メソッド名、状態名などに業務上の言葉を使うことで、コードと業務仕様が結び付きやすくなります。

共通理解があると、仕様変更や機能追加の議論がスムーズになります。開発者が業務の意味を理解しやすくなり、業務担当者もシステムの構造を説明しやすくなります。

4. ドメインモデルの構成要素

ドメインモデルは、さまざまな構成要素から成り立ちます。代表的なものに、エンティティ、値オブジェクト、ドメインサービスがあります。これらはドメイン駆動設計でも重要な概念です。

それぞれの要素には役割があります。エンティティは識別子を持つ重要な業務オブジェクト、値オブジェクトは値そのものに意味を持つオブジェクト、ドメインサービスは特定のエンティティや値オブジェクトに自然に置けない業務処理を扱います。

構成要素の比較

要素主な役割
エンティティ識別子を持つ業務オブジェクト注文、顧客、契約
値オブジェクト値そのものを表すオブジェクト金額、住所、期間
ドメインサービスモデル単体に置きにくい業務処理料金計算、審査、在庫引当

4.1 エンティティ

エンティティとは、識別子によって同一性を判断するドメインオブジェクトです。たとえば、顧客、注文、契約などは、属性が変わっても同じ識別子を持っていれば同じものとして扱われます。

エンティティには、業務上重要な振る舞いを持たせることができます。注文であれば、確定する、キャンセルする、支払い済みにするなどの振る舞いが考えられます。エンティティを単なるデータ入れ物として扱うのではなく、業務ルールを表現する中心として設計することが重要です。

4.2 値オブジェクト

値オブジェクトとは、識別子ではなく値そのものによって同一性を判断するオブジェクトです。たとえば、金額、住所、電話番号、期間、メールアドレスなどが値オブジェクトとして表現されます。値が同じであれば同じものとして扱われる点が特徴です。

値オブジェクトを使うと、業務上の意味をコードに表現しやすくなります。たとえば、金額を単なる数値で扱うのではなく、通貨や計算ルールを持つ金額オブジェクトとして扱えば、不正な操作を防ぎやすくなります。

4.3 ドメインサービス

ドメインサービスとは、特定のエンティティや値オブジェクトに自然に所属させにくい業務ロジックを扱う要素です。たとえば、複数の注文や在庫をまたぐ処理、外部条件を使った審査、複数オブジェクトの協調が必要な処理などが該当します。

ただし、すべてのロジックをドメインサービスに置いてしまうと、貧血ドメインモデルになりやすくなります。ドメインサービスは便利ですが、エンティティや値オブジェクトに置ける振る舞いまで外に出しすぎないように注意が必要です。

5. ドメイン駆動設計との関係

ドメインモデルは、ドメイン駆動設計と深く関係しています。ドメイン駆動設計とは、複雑な業務領域を正しく理解し、その知識をソフトウェア設計の中心に置く考え方です。ドメインモデルは、ドメイン駆動設計における中核的な要素の一つです。

ドメイン駆動設計では、単にデータベースや画面から設計するのではなく、業務上の概念やルールを中心にモデルを作ります。これにより、業務の変化に対応しやすく、ビジネス価値を反映しやすいシステムを実現できます。

5.1 ドメイン中心の設計

ドメイン駆動設計では、ドメインをシステム設計の中心に置きます。データベース構造やフレームワークの都合を優先するのではなく、業務の概念やルールを優先してモデルを設計します。

これにより、ビジネスロジックが技術詳細に埋もれにくくなります。業務ルールがドメインモデルとして表現されていれば、コードを読むことで業務の意味を理解しやすくなります。

5.2 ユビキタス言語

ユビキタス言語とは、開発者と業務担当者が共通して使う言葉のことです。ドメイン駆動設計では、業務上の言葉をモデル名やメソッド名にも反映し、会話とコードの間にズレが生まれにくいようにします。

たとえば、業務側が「注文確定」と呼んでいる処理を、コード上でもconfirmOrderや注文確定のように表現すれば、仕様と実装の対応が分かりやすくなります。ユビキタス言語は、ドメインモデルの品質を高める重要な考え方です。

5.3 モデルの継続的改善

ドメインモデルは、一度作って終わりではありません。業務理解が深まるにつれて、モデルも改善されるべきです。最初は単純に見えていた概念が、実は別の責務を持つことが分かる場合もあります。

ドメイン駆動設計では、モデルを継続的に見直し、業務の実態に近づけていくことが重要です。これにより、システムが業務の変化に対応しやすくなります。

6. リッチドメインモデルとは?

リッチドメインモデルとは、ドメインオブジェクトがデータだけでなく、業務上の振る舞いやルールも持つ設計スタイルです。注文オブジェクトが注文確定やキャンセルのルールを持ち、金額オブジェクトが計算や検証を持つような設計が該当します。

この設計では、業務ロジックがドメインモデル内に集約されます。モデル自身が業務上の意味を持ち、正しい状態遷移やルールを守るための振る舞いを提供します。オブジェクト指向らしい設計として評価されることが多いです。

主な特徴

項目内容
日本語リッチドメインモデル
英語名Rich Domain Model
特徴データと振る舞いを同じモデルに持つ
強み業務ルールを集約しやすい
向いている領域複雑な業務ルールを持つシステム

6.1 振る舞いを持つモデル

リッチドメインモデルでは、モデルが業務上の振る舞いを持ちます。たとえば、注文モデルが「確定する」「キャンセルする」「合計金額を計算する」といったメソッドを持つ場合、これは単なるデータ構造ではなく、業務ルールを表現するモデルになります。

振る舞いをモデル内に持たせることで、ルールの配置が明確になります。外部のサービス層に条件分岐を大量に書くのではなく、モデル自身が正しい振る舞いを提供するため、コードの意図が読み取りやすくなります。

6.2 データとロジックの統合

リッチドメインモデルでは、データとロジックを分離しすぎず、同じ業務概念の中にまとめます。これは、オブジェクト指向におけるカプセル化の考え方に近いものです。データを外部から自由に変更させるのではなく、モデルのメソッドを通じて安全に状態を変化させます。

この設計により、不正な状態を防ぎやすくなります。たとえば、注文ステータスを外部から自由に書き換えられる設計では、支払い前に発送済みにするような不整合が起きる可能性があります。モデル内に状態遷移ルールを持たせれば、このような不正を防ぎやすくなります。

6.3 オブジェクト指向らしい設計

リッチドメインモデルは、オブジェクト指向らしい設計とよく言われます。なぜなら、オブジェクトがデータと振る舞いを持ち、自分自身の状態やルールを管理するからです。

このような設計では、モデルが業務上の責任を持つため、コードが業務の言葉に近づきます。複雑なビジネスルールを扱うシステムでは、リッチドメインモデルによって設計の見通しが良くなることがあります。

7. リッチドメインモデルの特徴

リッチドメインモデルの特徴は、ビジネスルールをモデル内部に持つこと、カプセル化を活用すること、責務をドメインモデルに集約することです。この設計では、ドメインオブジェクトが単なるデータではなく、業務上の意味と振る舞いを持つ存在になります。

リッチドメインモデルを適切に設計すると、業務ルールの分散を防ぎ、一貫性を保ちやすくなります。ただし、すべての処理をモデルに詰め込むのではなく、そのモデルの責務として自然な処理を配置することが重要です。

7.1 ビジネスルールを内部に持つ

リッチドメインモデルでは、ビジネスルールをモデルの内部に持たせます。たとえば、注文がキャンセル可能かどうかの判定や、請求金額の計算、会員ランクに応じた制約などを、関連するモデルの振る舞いとして表現します。

これにより、業務ルールがどこにあるのか分かりやすくなります。サービス層や画面処理に同じ条件が分散することを防ぎ、仕様変更時の修正箇所も限定しやすくなります。

7.2 カプセル化の活用

リッチドメインモデルでは、カプセル化が重要です。カプセル化とは、内部状態を外部から直接変更させず、モデルが提供するメソッドを通じて操作させることです。これにより、不正な状態を防ぎやすくなります。

たとえば、注文ステータスを外部から自由に変更できる設計では、業務上あり得ない状態が作られる可能性があります。注文モデルに「確定する」「キャンセルする」などの操作を用意し、その中で状態遷移ルールを確認すれば、一貫性を保ちやすくなります。

7.3 責務の集中

リッチドメインモデルでは、関連する業務ルールをモデルに集中させます。これにより、注文に関するルールは注文モデル、金額に関するルールは金額オブジェクト、顧客に関するルールは顧客モデルというように、責務が明確になります。

責務が明確になると、コードを読む人が業務ルールを見つけやすくなります。また、変更時にもどこを修正すべきか判断しやすくなるため、保守性が向上します。

8. リッチドメインモデルのメリット

リッチドメインモデルのメリットは、保守性の向上、ドメイン知識の集約、一貫性の維持です。複雑な業務ルールを持つシステムでは、これらのメリットが大きくなります。業務ルールをモデル内に集約することで、仕様変更にも対応しやすくなります。

特に、長期運用される業務システムや、ドメイン駆動設計を採用するプロジェクトでは、リッチドメインモデルが有効になることがあります。モデルが業務知識を持つため、コードそのものが業務仕様を表現するようになります。

8.1 保守性向上

リッチドメインモデルでは、業務ルールがモデル内にまとまりやすいため、保守性が向上します。ルールが一箇所に集約されていれば、仕様変更時に修正箇所を見つけやすくなります。

また、同じルールを複数のサービスや画面に重複して書かなくて済むため、修正漏れのリスクも下がります。複雑な業務ロジックを扱うほど、このメリットは大きくなります。

8.2 ドメイン知識の集約

リッチドメインモデルでは、ドメイン知識がコード上のモデルに集約されます。モデル名、メソッド名、状態名が業務の言葉に近くなるため、コードを読むことで業務ルールを理解しやすくなります。

ドメイン知識が集約されると、開発チーム内の認識も揃いやすくなります。業務担当者との会話で使われる言葉とコードの構造が近くなるため、仕様のズレを減らす効果もあります。

8.3 一貫性の維持

リッチドメインモデルは、業務上の一貫性を維持しやすい設計です。モデル自身が状態変更やルール検証を行うため、不正な状態を作りにくくなります。

たとえば、注文確定前には請求できない、キャンセル済み注文は発送できない、といったルールをモデル内で保証できます。これにより、システム全体で一貫した振る舞いを保ちやすくなります。

9. リッチドメインモデルのデメリット

リッチドメインモデルには多くのメリットがありますが、設計難易度が高くなるというデメリットもあります。業務ルールをどのモデルに置くべきか、どこまでモデルに持たせるべきかを判断するには、ドメイン理解と設計経験が必要です。

また、小規模で単純なシステムにリッチドメインモデルを導入すると、過剰設計になる場合があります。業務ルールがほとんどなく、単純なデータ登録・更新が中心のシステムでは、シンプルな設計の方が適していることもあります。

9.1 設計難易度の上昇

リッチドメインモデルでは、業務ルールを適切なモデルに配置する必要があります。どの処理をエンティティに置き、どの処理を値オブジェクトに置き、どの処理をドメインサービスに置くべきかを判断しなければなりません。

この判断を誤ると、モデルが肥大化したり、責務が曖昧になったりします。リッチドメインモデルを成功させるには、業務理解と継続的なリファクタリングが重要です。

9.2 学習コスト

リッチドメインモデルは、単純なデータ中心設計に比べて学習コストがあります。ドメイン駆動設計、エンティティ、値オブジェクト、ドメインサービス、集約などの概念を理解する必要があるためです。

チーム全体がこれらの考え方を理解していない場合、設計方針がばらつく可能性があります。そのため、導入時には設計ルールやレビュー基準を共有することが重要です。

9.3 過剰設計のリスク

リッチドメインモデルを過度に適用すると、過剰設計になることがあります。単純なCRUD処理しかないシステムで、複雑なモデルや抽象化を導入すると、開発効率が下がる場合があります。

重要なのは、ドメインの複雑さに応じて設計を選ぶことです。リッチドメインモデルは強力ですが、すべてのプロジェクトに必要なわけではありません。

10. 貧血ドメインモデルとは?

貧血ドメインモデルとは、モデルがほとんど振る舞いを持たず、データだけを保持する設計スタイルです。英語ではAnemic Domain Modelと呼ばれます。モデルは主にプロパティと取得・設定メソッドを持ち、ビジネスロジックはサービス層など外部に配置されます。

この設計は実装が分かりやすく、単純なシステムでは扱いやすい場合があります。しかし、複雑な業務ルールを持つシステムでは、ロジックがサービス層に集中したり、複数箇所に分散したりすることで、保守性が低下することがあります。

主な特徴

項目内容
日本語貧血ドメインモデル
英語名Anemic Domain Model
特徴モデルがデータ中心で振る舞いを持たない
ロジック配置サービス層など外部に置かれる
向いている領域単純なCRUD中心のシステム

10.1 データ中心の設計

貧血ドメインモデルでは、モデルは主にデータを保持する役割を持ちます。たとえば、注文モデルが注文ID、顧客ID、金額、ステータスなどのプロパティを持つだけで、注文確定やキャンセルのルールは外部のサービスに実装されます。

この構造は、データベースのテーブル構造に近く、理解しやすい場合があります。特に単純な登録・更新・検索が中心のシステムでは、シンプルで実装しやすい設計になります。

10.2 振る舞いを持たないモデル

貧血ドメインモデルの特徴は、モデルが振る舞いをほとんど持たないことです。モデル自身は状態やルールを管理せず、外部のサービスがモデルのデータを読み取り、条件分岐や状態変更を行います。

この設計では、モデルは受動的なデータ構造になります。業務ルールはサービス層に集まりやすく、サービス層が肥大化する原因になることがあります。

10.3 Service層への依存

貧血ドメインモデルでは、ビジネスロジックがサービス層に置かれることが多くなります。サービス層は、モデルのデータを使って条件判定や処理を行います。

この構造は分かりやすい一方で、サービス層に多くの責務が集中しやすいという問題があります。業務ルールが増えるほど、サービス層が巨大化し、保守が難しくなる可能性があります。

11. 貧血ドメインモデルの特徴

貧血ドメインモデルの特徴は、取得・設定メソッド中心のモデル、ロジックの外部配置、シンプルな構造です。モデル自体が複雑な振る舞いを持たないため、最初の実装は分かりやすく、開発スピードも出しやすい場合があります。

一方で、業務ルールが増えてくると、どこにルールがあるのか分かりにくくなることがあります。特に、複数のサービスや画面に同じような条件判定が分散すると、修正漏れや不整合が発生しやすくなります。

11.1 GetterとSetter中心

貧血ドメインモデルでは、モデルが主に取得・設定メソッドを提供します。外部のサービス層がモデルの値を取得し、必要に応じて値を変更します。モデル自身は業務ルールをほとんど持ちません。

この構造は単純で理解しやすい反面、外部から自由に状態を変更できる設計になりやすいです。その結果、業務上不正な状態が作られる可能性があります。

11.2 ロジックの外部配置

貧血ドメインモデルでは、ビジネスロジックがサービス層やユースケース層に配置されます。たとえば、注文のキャンセル可否や金額計算などが、注文モデルではなく注文サービスに実装されます。

このような構造では、ロジックがサービス層に集中しやすくなります。最初は分かりやすくても、業務ルールが増えるとサービスが巨大化し、変更が難しくなる場合があります。

11.3 シンプルな構造

貧血ドメインモデルは構造がシンプルです。モデルはデータを持ち、サービスが処理を行うという分かりやすい分担になります。そのため、学習コストが低く、短期間で実装しやすいというメリットがあります。

ただし、シンプルさは業務ルールが少ない場合に有効です。業務ロジックが複雑になると、単純なデータ中心設計では限界が出ることがあります。

12. 貧血ドメインモデルのメリット

貧血ドメインモデルのメリットは、実装しやすいこと、理解しやすいこと、小規模開発と相性が良いことです。特に、単純なCRUD中心のアプリケーションでは、複雑なドメインモデルを作るよりも効率的な場合があります。

また、多くのフレームワークやORMでは、データベーステーブルに対応するモデルを作ることが多く、貧血ドメインモデルに近い形になりやすいです。そのため、実務ではよく見られる設計スタイルでもあります。

12.1 実装しやすい

貧血ドメインモデルは、モデルをデータ構造として作り、処理をサービス層に書くため、実装が分かりやすいです。特に初心者や小規模チームでは、設計方針を共有しやすいというメリットがあります。

複雑なドメイン設計を行わなくても、基本的な登録・更新・削除・検索を実装できます。短期間で機能を作る必要がある場合には、有効な選択肢になることがあります。

12.2 理解しやすい

貧血ドメインモデルは、データと処理の分担が明確です。モデルはデータ、サービスは処理という構造になるため、最初に見たときには理解しやすい場合があります。

また、データベース中心の設計と対応しやすいため、テーブル構造からモデルを想像しやすいという利点もあります。単純なアプリケーションでは、この分かりやすさが大きなメリットになります。

12.3 小規模開発との相性

小規模なシステムや業務ルールが少ないアプリケーションでは、貧血ドメインモデルの方が適している場合があります。複雑なモデル設計を行うよりも、シンプルな構造で素早く開発できるためです。

たとえば、管理画面や単純なマスタ管理システムでは、リッチドメインモデルを導入してもメリットが小さいことがあります。要件の複雑さに応じて設計を選ぶことが重要です。

13. 貧血ドメインモデルのデメリット

貧血ドメインモデルのデメリットは、ロジックの分散、保守性低下、ドメイン駆動設計との相性の悪さです。業務ルールが複雑になるほど、これらの問題が表面化しやすくなります。

特に、サービス層に大量の条件分岐が集まると、サービスが巨大化し、何を担当しているのか分かりにくくなります。また、同じルールが複数のサービスや画面に重複して実装されることもあります。

13.1 ロジックの分散

貧血ドメインモデルでは、モデルが振る舞いを持たないため、業務ロジックが外部に配置されます。その結果、同じ業務ルールが複数のサービスやコントローラーに分散することがあります。

ロジックが分散すると、仕様変更時に修正箇所を見つけにくくなります。また、一部だけ修正されて他の箇所が古いまま残ると、システム内で不整合が発生します。

13.2 保守性低下

業務ルールが増えるほど、貧血ドメインモデルは保守性が低下しやすくなります。サービス層が肥大化し、条件分岐が増え、処理の見通しが悪くなるためです。

保守性を維持するには、サービス層にロジックを集めすぎないことが重要です。必要に応じて、エンティティ、値オブジェクト、ドメインサービスへ責務を分配する必要があります。

13.3 DDDとの相性の悪さ

貧血ドメインモデルは、ドメイン駆動設計とは相性が悪いとされることが多いです。ドメイン駆動設計では、ドメインモデルが業務知識や振る舞いを表現することが重要ですが、貧血ドメインモデルではモデルがデータ中心になるためです。

ただし、すべての貧血ドメインモデルが悪いわけではありません。業務ルールが少ないシステムでは、シンプルな設計として有効な場合もあります。重要なのは、ドメインの複雑さに応じて判断することです。

14. リッチドメインモデルと貧血ドメインモデルの違い

リッチドメインモデルと貧血ドメインモデルの違いは、責務の配置とビジネスロジックの管理方法にあります。リッチドメインモデルでは、モデル自身が業務ルールや振る舞いを持ちます。貧血ドメインモデルでは、モデルはデータを保持し、業務ロジックはサービス層など外部に配置されます。

どちらが絶対に正しいというものではありません。複雑な業務ルールを持つシステムではリッチドメインモデルが有効になりやすく、単純なCRUD中心のシステムでは貧血ドメインモデルでも十分な場合があります。重要なのは、プロジェクトの要件に合った設計を選ぶことです。

比較表

項目リッチドメインモデル貧血ドメインモデル
モデルの役割データと振る舞いを持つ主にデータを保持する
ロジック配置モデル内部サービス層など外部
保守性複雑な業務で高くなりやすいロジック増加時に低下しやすい
学習コスト高め低め
向いているケース複雑な業務ルール単純なCRUD

14.1 責務の配置

リッチドメインモデルでは、業務ルールに関する責務をモデルに配置します。注文に関するルールは注文モデル、金額に関するルールは金額オブジェクトというように、責務が業務概念に沿って配置されます。

一方、貧血ドメインモデルでは、モデルはデータを持つだけで、責務はサービス層に置かれます。これにより構造は単純になりますが、サービス層が多くの責務を持ちやすくなります。

14.2 ビジネスロジックの管理方法

リッチドメインモデルでは、ビジネスロジックをドメインモデル内で管理します。これにより、ロジックの重複や分散を防ぎやすくなります。

貧血ドメインモデルでは、ビジネスロジックをサービス層で管理します。この方法は分かりやすい一方で、業務ルールが増えるとサービス層が複雑化しやすくなります。

14.3 設計思想の違い

リッチドメインモデルは、オブジェクトがデータと振る舞いを持つというオブジェクト指向的な考え方に近いです。ドメインモデルをシステムの中心に置き、業務ルールを表現することを重視します。

貧血ドメインモデルは、データと処理を分ける考え方に近いです。単純で分かりやすい反面、複雑な業務ルールを表現するには工夫が必要になります。

15. ビジネスロジックはどこに置くべきか

ビジネスロジックをどこに置くべきかは、ドメインモデル設計で非常に重要な判断です。すべてのロジックをエンティティに置くべきではありませんし、すべてをサービス層に置くべきでもありません。ロジックの性質に応じて、適切な場所を選ぶ必要があります。

基本的には、特定のエンティティや値オブジェクトに自然に属するルールはそのモデルに置きます。複数のモデルにまたがるルールや、単一のモデルに置くと不自然な処理はドメインサービスに置きます。アプリケーションの流れを制御する処理はアプリケーションサービスに置きます。

15.1 Entityに置く場合

エンティティに置くべきロジックは、そのエンティティ自身の状態や振る舞いに関するものです。たとえば、注文を確定する、注文をキャンセルする、ステータスを変更する、といった処理は注文エンティティに置くのが自然です。

エンティティにロジックを置くことで、状態変更のルールをモデル内で管理できます。外部から自由に状態を変更するのではなく、エンティティのメソッドを通じて安全に操作することで、一貫性を保ちやすくなります。

15.2 Domain Serviceに置く場合

ドメインサービスに置くべきロジックは、特定のエンティティや値オブジェクトに自然に所属しない業務処理です。たとえば、複数の在庫から引当を行う処理や、複数の契約条件を使って審査する処理などが該当します。

ドメインサービスは便利ですが、使いすぎるとロジックがドメインサービスに集中し、貧血ドメインモデルに近づいてしまいます。エンティティや値オブジェクトに置ける処理まで外に出さないように注意が必要です。

15.3 Application Serviceに置く場合

アプリケーションサービスに置くべき処理は、ユースケースの流れを制御する処理です。たとえば、入力を受け取り、リポジトリからモデルを取得し、ドメインモデルのメソッドを呼び出し、結果を保存するような処理が該当します。

アプリケーションサービスは、業務ルールそのものを持つ場所ではありません。業務ルールはドメインモデルやドメインサービスに置き、アプリケーションサービスは処理の流れを調整する役割にとどめることが望ましいです。

16. オブジェクト指向設計との関係

ドメインモデルは、オブジェクト指向設計と深く関係しています。オブジェクト指向では、データと振る舞いをまとめ、責務を持つオブジェクトとして設計します。リッチドメインモデルは、この考え方を業務ルールの表現に活用したものです。

一方で、貧血ドメインモデルは、オブジェクトがデータだけを持ち、処理を外部に置くため、オブジェクト指向の利点を十分に活かせないと批判されることがあります。ただし、状況によってはシンプルな設計として有効な場合もあります。

16.1 カプセル化

カプセル化とは、オブジェクトの内部状態を外部から直接変更させず、メソッドを通じて操作させる考え方です。ドメインモデルでは、業務上不正な状態を防ぐためにカプセル化が重要になります。

たとえば、注文ステータスを外部から自由に変更できる設計では、業務上あり得ない状態が作られる可能性があります。注文モデルが状態遷移のメソッドを提供し、その中でルールを検証することで、安全な設計になります。

16.2 責務の分離

責務の分離とは、各オブジェクトやモジュールが明確な役割を持つように設計することです。ドメインモデルでは、業務概念ごとに責務を分けることが重要です。

責務が明確であれば、コードの意図が分かりやすくなります。変更時にも、どのモデルを修正すべきか判断しやすくなるため、保守性が向上します。

16.3 情報隠蔽

情報隠蔽とは、内部実装の詳細を外部に見せないようにする考え方です。ドメインモデルでは、内部状態や計算方法を外部に公開しすぎないことが重要です。

情報隠蔽により、内部実装を変更しても外部への影響を抑えられます。これは、長期的に変更しやすいドメインモデルを作るために重要な原則です。

17. SOLID原則との関係

ドメインモデルは、SOLID原則とも関係しています。特に、単一責任の原則、オープン・クローズドの原則、依存性逆転の原則は、ドメインモデル設計において重要です。これらを意識することで、保守性と拡張性の高いモデルを作りやすくなります。

ただし、SOLID原則を機械的に適用すれば良いわけではありません。ドメインの複雑さや変更頻度に応じて、適切な粒度で適用することが重要です。

17.1 SRPとの関係

単一責任の原則は、ドメインモデルの責務を明確にするうえで重要です。1つのモデルが複数の変更理由を持つと、保守が難しくなります。

たとえば、注文モデルが注文ルールだけでなく、メール送信やデータ保存まで担当している場合、責務が混在しています。このような処理は、通知サービスやリポジトリに分離するべきです。

17.2 OCPとの関係

オープン・クローズドの原則は、ドメインモデルの拡張性に関係します。新しい業務ルールが追加されたときに、既存コードを大きく修正せずに対応できる設計が望まれます。

たとえば、割引ルールが増えるたびに巨大なif文を修正する設計では、変更リスクが高くなります。ルールを戦略として分けるなどの設計にすれば、拡張しやすくなります。

17.3 DIPとの関係

依存性逆転の原則は、ドメインモデルを外部技術から守るために重要です。ドメインモデルがデータベース、外部API、フレームワークに直接依存すると、技術変更の影響を受けやすくなります。

ドメインモデルは、できるだけ業務ルールに集中し、永続化や外部連携の詳細から独立させるべきです。これにより、テストしやすく、変更に強い設計になります。

18. リポジトリとの関係

リポジトリは、ドメインモデルの永続化を扱うための設計パターンです。ドメインモデルは業務ルールを表現し、リポジトリはそのモデルを保存・取得する責務を持ちます。この分離により、ドメインモデルがデータベースの詳細に依存しにくくなります。

リポジトリを適切に使うことで、ドメイン層とインフラ層を分離できます。これにより、データベースを変更しても、ドメインモデルへの影響を抑えやすくなります。

18.1 永続化の責務

永続化とは、ドメインモデルの状態をデータベースなどに保存することです。リポジトリは、この永続化の責務を持ちます。ドメインモデル自身がSQLやデータベース接続を扱うべきではありません。

永続化の責務をリポジトリに分けることで、ドメインモデルは業務ルールに集中できます。これは、クリーンアーキテクチャやドメイン駆動設計でも重要な考え方です。

18.2 ドメインモデルとの分離

リポジトリは、ドメインモデルとデータベースの間に位置する抽象です。ドメインモデルは保存方法を知らず、リポジトリを通じて取得・保存されます。

この分離により、データベースの変更やORMの変更がドメインモデルに直接影響しにくくなります。テスト時にも、リポジトリをモックに差し替えることができます。

18.3 データアクセス管理

リポジトリは、データアクセスを管理する役割を持ちます。検索条件、保存処理、更新処理などをリポジトリにまとめることで、データアクセスの責務が明確になります。

ただし、リポジトリに業務ロジックを入れすぎるのは避けるべきです。リポジトリはあくまで永続化の窓口であり、業務ルールはドメインモデルやドメインサービスに置くのが基本です。

19. ドメインサービスとの関係

ドメインサービスは、エンティティや値オブジェクトに自然に置けない業務ロジックを扱うための要素です。複数のドメインオブジェクトにまたがる処理や、単一のモデルに所属させると不自然な処理を表現するために使われます。

ただし、ドメインサービスは使い方に注意が必要です。すべての業務ロジックをドメインサービスに置くと、モデルがデータだけになり、貧血ドメインモデルに近づきます。ドメインサービスは、必要な場合に限定して使うことが重要です。

19.1 エンティティに置けない処理

ある業務ロジックが特定のエンティティに自然に属さない場合、ドメインサービスに置くことがあります。たとえば、複数の口座間の送金処理や、複数在庫を横断した引当処理などです。

このような処理を無理に1つのエンティティに置くと、責務が不自然になります。ドメインサービスを使うことで、複数オブジェクトにまたがるルールを表現しやすくなります。

19.2 複数オブジェクトの協調

ドメインサービスは、複数のドメインオブジェクトが協調する処理に向いています。たとえば、顧客、注文、在庫、支払い条件を組み合わせて注文可否を判定するような処理です。

ただし、協調処理の中でも、各モデルに任せられる処理はモデルに置くべきです。ドメインサービスは全体の調整を行い、個別のルールは各モデルに任せると、責務が整理されます。

19.3 ドメインルール管理

ドメインサービスは、ドメインルールを管理する役割を持つことがあります。特定のモデルに属さないが、業務上重要なルールを表現する場所として利用されます。

ただし、ドメインサービスが肥大化すると、サービス層にロジックが集中する問題が発生します。ドメインサービスは、モデル設計とバランスを取りながら使うことが重要です。

20. Web開発での活用

ドメインモデルは、Web開発でも有効に活用できます。特に、業務ルールが複雑なWebアプリケーションでは、ドメインモデルを中心に設計することで、保守性と拡張性を高められます。

Web開発では、コントローラー、サービス、リポジトリ、データベースなど多くの層が登場します。ドメインモデルを適切に設計すれば、業務ルールが特定の層に散らばることを防ぎやすくなります。

20.1 業務システム

業務システムでは、承認フロー、権限、契約条件、請求ルールなど、複雑な業務ルールが多く存在します。これらをドメインモデルとして表現することで、ルールの一貫性を保ちやすくなります。

業務システムは長期運用されることが多いため、保守性が非常に重要です。ドメインモデルを適切に設計することで、仕様変更に対応しやすい構造を作れます。

20.2 ECサイト

ECサイトでは、商品、注文、在庫、決済、配送、クーポン、会員ランクなど、多くのドメイン概念が存在します。特に注文や決済に関するルールは複雑になりやすいため、ドメインモデルが有効です。

たとえば、注文確定、在庫引当、割引適用、キャンセル可否などをモデルとして表現すれば、業務ルールが明確になります。機能追加やキャンペーン対応にも強い設計を作りやすくなります。

20.3 SaaSアプリケーション

SaaSアプリケーションでは、契約プラン、ユーザー権限、利用制限、課金、通知、ワークスペース管理などのドメイン概念が重要になります。これらを単なるデータとして扱うと、ロジックが分散しやすくなります。

ドメインモデルを使うことで、プランごとの制約や権限ルールを整理できます。特に、複数プランや複雑な課金体系を持つSaaSでは、ドメインモデルの設計が重要です。

21. マイクロサービスとの関係

ドメインモデルは、マイクロサービス設計とも関係しています。マイクロサービスでは、サービス境界をどのように分けるかが非常に重要です。ドメインの境界を正しく理解していないと、サービス間の依存が複雑になり、かえって保守が難しくなります。

ドメインモデルを使うことで、業務上の境界を整理しやすくなります。どの概念が同じサービスに属するべきか、どのルールを独立させるべきかを考える際に、ドメインモデルは重要な判断材料になります。

21.1 サービス境界

マイクロサービスでは、サービス境界を業務ドメインに基づいて設計することが重要です。たとえば、注文管理、在庫管理、請求管理、顧客管理などは、それぞれ異なるドメイン境界を持つ可能性があります。

サービス境界が適切であれば、各サービスは独立して開発・運用しやすくなります。逆に境界が曖昧だと、サービス間で同じルールが重複したり、頻繁に連携が必要になったりします。

21.2 ドメイン分割

ドメイン分割では、業務上の概念やルールを分析し、どの単位でモデルを分けるかを考えます。これは境界づけられたコンテキストの考え方とも関係します。

同じ言葉でも文脈によって意味が異なる場合があります。たとえば、「顧客」という言葉は、販売管理とサポート管理では異なる意味を持つことがあります。ドメイン分割では、このような文脈の違いを考慮する必要があります。

21.3 独立性向上

適切なドメインモデルとサービス境界を設計すると、各サービスの独立性が高まります。独立性が高いサービスは、変更やリリースを個別に行いやすくなります。

独立性を高めるには、共有データベースや過剰なサービス間依存を避けることも重要です。ドメインモデルは、どのデータとルールをどのサービスが所有するべきかを考えるための基盤になります。

22. リッチドメインモデルが向いているケース

リッチドメインモデルは、複雑な業務ルールを持つシステム、長期運用されるシステム、ドメイン駆動設計を採用するプロジェクトに向いています。業務ルールが多く、変更頻度も高い場合、ドメイン知識をモデル内に集約するメリットが大きくなります。

ただし、リッチドメインモデルは設計難易度が高いため、チームに十分な理解が必要です。導入する場合は、モデルの責務やロジック配置のルールを共有し、継続的に改善することが重要です。

22.1 複雑な業務ルール

複雑な業務ルールを持つシステムでは、リッチドメインモデルが有効です。注文、契約、請求、承認、権限、在庫など、複数の条件が絡む処理では、ルールをモデル内にまとめることで保守性が高まります。

業務ルールが複雑な場合、サービス層だけで処理を管理すると条件分岐が肥大化しやすくなります。リッチドメインモデルを使えば、各モデルが自分の責務を持ち、ルールを自然に表現できます。

22.2 長期運用システム

長期運用されるシステムでは、保守性が非常に重要です。初期開発時のスピードだけを重視すると、後から仕様変更が難しくなり、技術的負債が増える可能性があります。

リッチドメインモデルは、長期的な変更に対応しやすい構造を作るために有効です。業務ルールをモデルに集約しておけば、変更時の影響範囲を把握しやすくなります。

22.3 DDD採用プロジェクト

ドメイン駆動設計を採用するプロジェクトでは、リッチドメインモデルが選ばれることが多くあります。ドメイン駆動設計では、ドメインモデルが業務知識を表現する中心的な役割を持つためです。

ただし、DDDを採用するからといって、すべてをリッチにすれば良いわけではありません。ドメインの重要度や複雑さに応じて、モデルの深さを調整することが重要です。

23. 貧血ドメインモデルが向いているケース

貧血ドメインモデルは、CRUD中心のシステム、小規模プロジェクト、シンプルな業務要件に向いています。業務ルールが少なく、単純にデータを登録・更新・表示するだけであれば、複雑なドメインモデルを作る必要はない場合があります。

重要なのは、貧血ドメインモデルを無条件に悪いものと考えないことです。設計は目的に応じて選ぶべきです。シンプルな要件に対してシンプルな設計を使うことは、実務上合理的な判断です。

23.1 CRUD中心のシステム

CRUD中心のシステムでは、データの作成、取得、更新、削除が主な処理になります。業務ルールが少ない場合、モデルに複雑な振る舞いを持たせる必要はありません。

たとえば、単純なマスタ管理画面や内部管理ツールでは、貧血ドメインモデルでも十分に対応できることがあります。過剰な設計を避けることも重要です。

23.2 小規模プロジェクト

小規模プロジェクトでは、開発スピードやシンプルさが重視されることがあります。チーム人数が少なく、要件も単純な場合、複雑なドメイン設計を導入すると開発負荷が高くなる可能性があります。

そのような場合は、貧血ドメインモデルを使ってシンプルに実装し、必要に応じて後からリッチドメインモデルへ改善する方法もあります。最初から過剰に設計しないことが重要です。

23.3 シンプルな業務要件

業務要件がシンプルな場合、貧血ドメインモデルは有効です。複雑な状態遷移や業務ルールがない場合、モデルに振る舞いを持たせてもメリットが小さいことがあります。

ただし、将来的に業務ルールが増える可能性が高い場合は注意が必要です。最初はシンプルでも、成長に応じてモデル設計を見直すことが重要です。

24. 実務でのベストプラクティス

実務では、リッチドメインモデルと貧血ドメインモデルを二者択一で考えるのではなく、ドメインの複雑さに応じて使い分けることが重要です。複雑な業務ルールにはリッチなモデルを使い、単純なデータ管理にはシンプルなモデルを使うという判断が現実的です。

また、設計は一度決めたら終わりではありません。業務理解が深まったり、要件が変化したりした場合は、モデルを継続的に見直す必要があります。過剰設計を避けつつ、必要な部分には十分なドメイン表現を持たせることが重要です。

24.1 ドメインの複雑さに応じて選択する

設計スタイルは、ドメインの複雑さに応じて選ぶべきです。業務ルールが複雑で変更頻度が高い場合は、リッチドメインモデルが有効です。一方、単純なCRUD処理であれば、貧血ドメインモデルでも問題ない場合があります。

重要なのは、モデルの複雑さと業務の複雑さを一致させることです。単純な業務に過剰なモデルを作る必要はありませんが、複雑な業務を単純なデータ構造だけで扱うと、後から保守が難しくなります。

24.2 業務ルールを適切に配置する

業務ルールは、最も自然な場所に配置することが重要です。エンティティ自身の状態に関するルールはエンティティへ、値の整合性に関するルールは値オブジェクトへ、複数オブジェクトにまたがるルールはドメインサービスへ配置します。

アプリケーションサービスやコントローラーに業務ルールを置きすぎると、ドメインモデルが形だけになってしまいます。処理の流れと業務ルールを分けて考えることが大切です。

24.3 過剰設計を避ける

ドメインモデル設計では、過剰設計を避けることも重要です。リッチドメインモデルを意識しすぎて、必要以上に多くのクラスや抽象化を作ると、かえって理解しにくい設計になります。

良い設計とは、複雑なものを必要以上に複雑にすることではありません。業務の複雑さを適切に表現しつつ、できるだけシンプルに保つことが重要です。

おわりに

ドメインモデルは、ビジネスルールやドメイン知識をソフトウェア上で表現するための重要な設計手法です。特に業務システムでは、注文、契約、請求、在庫、権限などの複雑なルールをどのように表現するかが、システムの保守性や拡張性に大きく影響します。

リッチドメインモデルは、データと振る舞いを同じモデル内に持たせる設計スタイルです。業務ルールをモデルに集約でき、一貫性を保ちやすく、複雑なドメインを扱うシステムに向いています。一方で、設計難易度や学習コストが高く、単純なシステムでは過剰設計になる可能性もあります。

貧血ドメインモデルは、モデルをデータ中心に扱い、ビジネスロジックをサービス層など外部に置く設計スタイルです。実装しやすく、理解しやすく、小規模なCRUD中心のシステムと相性が良いです。ただし、業務ルールが複雑になると、ロジックが分散したりサービス層が肥大化したりするリスクがあります。

重要なのは、どちらが絶対に正しいかではなく、ドメインの複雑さやプロジェクトの目的に応じて適切に選択することです。複雑な業務ルールにはリッチドメインモデルを活用し、単純なデータ管理にはシンプルな設計を選ぶという判断が実務では有効です。

ドメインモデル設計では、業務ルールを自然な場所に配置し、責務を明確にし、必要に応じてエンティティ、値オブジェクト、ドメインサービス、リポジトリを使い分けることが重要です。ドメインの複雑さに応じた適切な設計判断を行うことで、長期的に保守しやすく、変更に強いソフトウェアを実現できるでしょう。

LINE Chat