モジュールの命名規約
モジュール名の決め方は、JavaやC#の一般的な命名方針に従い、ピリオドにて区切られた階層構造にて記述します。階層構造の先頭には、組織名を使うことが一般的です。SaaSOvationの例を見ていきましょう。
// Javaの場合 com.saasovation // C#の場合 SaaSOvation
トップレベル名として組織名を設定しています。Javaの場合、インターネットドメイン名(comやjp)が一般的なため、ここではcomという名前で始めています。このような命名規約を使うことで、JARやDLLにおいて他プロジェクトとの衝突を避けることができます。
トップレベル下のコンテキスト名
トップレベルの組織名を決めた後は、その下の名前を検討します。ここでのポイントは、idovation/collabovation/projectovationといったプロダクト名を入れていないことです。その代わり「境界づけられたコンテキスト」に沿った名前を追加しています。
SaaSOvation.IdentityAccess SaaSOvation.Collaboration SaaSOvation.AgilePM
コンテキスト名が必ず正しいわけではありませんが、SaaSOvationでは、この名称がユビキタス言語を示す上でわかりやすいといった理由で命名しています。この場合、プロダクト名の変更の影響を受けないメリットがあります。
重要なサブモジュール名
さらに続けて、コンテキスト名の下位にあたる階層名について考えてみましょう。
SaaSOvation.IdentityAccess.Domain SaaSOvation.Collaboration.Domain SaaSOvation.AgilePM.Domain
ここでは「Domain」というモジュール名を追加しています。この配下にはドメインに関する情報を格納します(このDomainフォルダの直下にはクラスは存在せず、その下位のサブフォルダの中に格納します)。
SaaSOvation.IdentityAccess.Domain.Model SaaSOvation.Collaboration.Domain.Model SaaSOvation.AgilePM.Domain.Model
次にDomain配下に「Model」を追加しています。この「Model」配下のサブモジュールには、値オブジェクト、エンティティ、イベントといったクラスやインタフェースが定義されます。
さらに次の階層について検討してみましょう。
SaaSOvation.AgilePM.Domain.Service
このモジュール名は良さそうに見えますが、Serviceという名前は「ドメインモデル貧血症」という中身のないモデルがたくさん作られるきっかけになりがちです。ドメインサービスの章にて紹介したように、ビジネスロジックが全てサービスクラスに記述してしまわないように注意します。
SaaSOvation.AgilePM.Domain.<コンセプト名>
そこで、ドメインモデル内でサービスという用語を使わず、ドメインのコンセプトを示す名前(Products、Tenants、Teams等)をつけます。このモジュール名はチームで検討し、チームの会話で利用します。
モジュール間の依存関係
命名方法に続けて、各モジュールにどのようなクラスが含まれているのかを見ていきましょう。また、それぞれのモジュールが持っている依存関係も見ていきましょう。
SaaSOvation.AgilePM.Domain.Model.Tenants SaaSOvation.AgilePM.Domain.Model.Teams SaaSOvation.AgilePM.Domain.Model.Products
アジャイル管理コンテキストのドメインモデル配下の場合、「テナント(Tenants)」「チーム(Teams)」「プロダクト(Products)」といったサブモジュールが存在しています。
テナントモジュール
「テナント(Tenants)」モジュールに存在するクラスは、TeanatId(値オブジェクト)です。これはエンティティの章にて紹介した一意な識別子で、個々のテナントを区別するキーとなります(このTeanatIdは「アジャイル管理プロジェクト」だけの識別子ではなく、本来は「認証・アクセスコンテキスト」側で使われる識別子となります)。
このテナントモジュール(TeanatId)は、アジャイル管理コンテキストの他のほとんどのモジュールから参照されます。しかし、逆方向の参照はしていないので、シンプルな依存関係といえます。
チームモジュール
2つ目の「チーム(Teams)」モジュールを見ていきます。このモジュールには、チームを管理するために使う3つの集約(ProductOwner、Team、TeamMember)が含まれています。
1つのモジュールの中に、チーム管理に関連する「リポジトリ」「集約」「値オブジェクト」といった複数のドメインオブジェクトが格納されていることがわかります。その「プロダクトオーナー(ProductOwner)」の場合、「プロダクトモジュール」から参照され、「テナントモジュール」を参照していることもわかります。これも比較的わかりやすい依存関係になります。
プロダクトモジュール
3つ目の「プロダクト(Products)」モジュールの中には、本来60近いクラス群が含まれていました。そこで、SaaSOvationでは、ユビキタス言語に沿って「スプリント(Sprints)」「バックログ(BacklogItems)」「リリース(Release)」といったサブモジュールを作成し、その中にクラスを分けて配置するようにしました。
このモジュールは親子関係内にて双方向の依存関係となっています。本来は双方向の依存関係は避けたいところですが、最初に述べたルールにあるように、ここは管理のためにモジュールに分割した領域のため、双方向でも問題ないこととしています。
