モジュールとは
「モジュール」とは、オブジェクトをまとめて管理する仕組みのことを表します。プログラミング言語の機能としては、Javaではパッケージ、C#では名前空間と呼ばれています。本稿では、このモジュールをDDDでどのように設計していくかについて紹介していきます。
DDDでのモジュールとは
「モジュール」はプログラム言語における「パッケージ」や「名前空間」にあたり、クラス群をまとめて管理する入れ物となります。この機能により、クラス群の責任と役割を明確にして、保守性や可読性を上げることができます。DDD本でEvans氏は
モジュールを選択する際には、システムに関する物語を伝え、概念の凝集した集合を含んでいるものを選ぶこと。こうすることで、モジュール間は低結合になることが多い。(略)モジュールとその名前はドメインに対する洞察を反映していなければならない。
と、モジュールについて述べています。この説明からわかるように、DDDではソースファイルを物理的に分けるだけではなく、高凝縮で低結合なモジュール化されたモデルを、ユビキタス言語に従って構築することを推奨しています。
簡単な例を見てみましょう。上図では「道具」という1つのモジュールを、「キッチン引き出し」と「ガレージ工具箱」の2つのモジュールに分割しています。ナイフ、フォーク、お皿はキッチンで一緒に使う(依存関係があり凝集性が高い)ため同じモジュールにしています。そして、一緒に使わない(結合度が低い)ガレージ工具類を別のモジュールとして設計しています。
このように、モジュール設計では凝集度と結合度の両方を意識します。
高いほど好ましい「凝集度(ぎょうしゅうど)」
凝集度(cohesion)とは、モジュールのまとまり具合に関する指標です。特定の機能に対する責任を持って、正しくまとまって協調しているかを示す指標で、高いほうが良いとされます。文脈的に強度(strength)と呼ばれることもあり、この場合は強いほうが良いとされます。
低いほど好ましい「結合度」
結合度(coupling)とは、モジュールを変更しやすいように適切に分割できているかどうかを示す指標です。密結合(結合度が高)なシステムでは修正が困難になるため、疎結合(結合度が低)なシステムが良いとされます。
必要な機能がまとまっていれば、外部のモジュールと連携する必要がないため、凝集度が高くなれば、結合度は低くなります。逆に、凝集度が低くなれば結合度が高くなる傾向があります。言うまでもなく、特定モジュール内の変更が別のモジュールに影響を与えてしまうような、低凝集かつ高結合のシステムは好ましくありません。
モジュールの設計方法
モジュール設計における重要なポイントとして、まず「モジュールの存在を軽視しない」ことを挙げています。エンティティ/値オブジェクト/サービス/イベントと同じ扱いで、モジュールについても十分に議論するようにします。
モデリングする際には、正確な意図が伝わるようにモジュール名を検討します。必要があれば恐れずにモジュール名の変更を行います。ドメインエキスパートとディスカッションしている最新情報がモジュールに反映されるように努めます。
IDDDにおけるモジュールの設計ルール
IDDDではモジュールを設計する指針として、以下を整理しています。
番号 | モジュールの設計指針 |
---|---|
1 | モジュールをDDDにおいて非常に重要な概念と認識し、モデリングの概念にフィットさせ設計する。例えば、集約に対して1つのモジュールを用意する。 |
2 | モデリングの概念に従い、モジュール名をユビキタス言語に従う。 |
3 | モジュール名を機械的に決めない。例えば、クラスの型や役割だけでまとめるようなモジュールを作らない。 |
4 | 疎結合に設計する。極力、他のモジュールに依存しないようにする。 |
5 | モジュール同士の結合が必要な場合に、循環依存が起きないようにする。意味的に双方向な依存関係があっても実装上は単一方向の依存関係が望ましい。 |
6 | モジュール間の循環依存は避けるべきだが、親子関係(上位と下位関係)のモジュールに限り、やむをえない場合がある。 |
7 | 取りまとめているオブジェクト群に合わせた名前をつけ、そぐわない場合はリファクタリングする。 |
これらの指針では、ユビキタス言語や凝集度、結合度、依存関係(循環参照)といった観点を意識していることがわかります。