(3)サービスに実装するファクトリ
次に、サービスに実装するファクトリを見ていきましょう。まず、ファクトリを呼び出す部分から見ていきます。
namespace SaaSOvation.Collaboration.Application.Forums
{
// フォーラムのアプリケーションサービス
public class ForumApplicationService
{
// フォーラムにモデレーターをアサインする
public void AssignModeratorToForum(string tenantId,
string forumId, string moderatorId)
{
var tenant = new Tenant(tenantId);
var forum = this.forumRepository.Get(tenant, new ForumId(forumId));
// ファクトリ「GetModeratorFrom」経由でモデレーターを生成する
var moderator = this.collaboratorService.GetModeratorFrom(tenant, moderatorId);
forum.AssignModerator(moderator);
this.forumRepository.Save(forum);
}
}
}
上記のコードは「ForumApplicationService」クラスの「AssignModeratorToForum」メソッドで、フォーラムにモデレーターをアサインしています。この中で、ファクトリの「GetModeratorFrom」を呼び出していることが分かります。
ドメインサービス上のファクトリのコード例
このファクトリのコードを見てみましょう。このドメインサービスでは「Get<生成する種類>From」という複数のファクトリのメソッドが用意されています。戻り値として「投稿者/作成者/モデレーター/所有者/参加者」のインスタンスを生成して戻しています。
namespace SaaSOvation.Collaboration.Domain.Model.Collaborators
{
// 変換用のドメインサービス
public interface ICollaboratorService
{
// 投稿者を生成して取得
Author GetAuthorFrom(Tenant tenant, string identity);
// 作成者を生成して取得
Creator GetCreatorFrom(Tenant tenant, string identity);
// モデレーターを生成して取得
Moderator GetModeratorFrom(Tenant tenant, string identity);
// 所有者を生成して取得
Owner GetOwnerFrom(Tenant tenant, string identity);
// 参加者を生成して取得
Participant GetParticipantFrom(Tenant tenant, string identity);
}
}
6章の「値オブジェクト」でも紹介した通り、「人」という概念でも、認証・アクセスコンテキストでは「ユーザー/ロール」というモデルになったり、コラボレーションコンテキストでは「投稿者/作成者/モデレーター/所有者/参加者」という別のモデル(ユビキタス言語)になったりします。
このように他の境界づけられたコンテキストの情報を使ってオブジェクトを生成する時にもファクトリを使用します。このオブジェクトの生成に関する主要なクラス群は下図の通りです。
このファクトリでは、認証アクセスコンテキストの公開ホストサービスを呼び出してユーザー情報を取り出し、必要とするコラボレータの派生クラスを生成しています。RESTサービスを呼び出したり、型の変換を行ったりと、生成処理は複雑ですが、ファクトリを呼び出すクライアント側では、その複雑さが見えないように実装できていることが分かります。
この具体的な実装については、GitHubのコード(ドメインモデル側やインフラストラクチャ側)を見てみると良いでしょう。
以上、サービス上のファクトリにて、境界づけられたコンテキスト間の変換が可能なことが理解できたかと思います。
[コラム]優れたファクトリとデザインパターン
優れたファクトリの設計について、エヴァンス氏はDDD本において下記のように述べています。
複雑な組み立てをすべてカプセル化するインターフェイスを提供すること。その際に、インスタンス化されるオブジェクトの具象クラスを、クライアントが参照しなくても良いようにすること。
さらにこの説明として、優れたファクトリは「生成される具象クラスではなく、要求される型に応じて抽象化されないといけない」と述べています。
これらを満たすファクトリの実装には、書籍「オブジェクト指向の再利用のためのデザインパターン」の「ファクトリメソッド」「アブストラクトファクトリ」「ビルダー」といったプログラミングパターンがよく使われます。また、変換を行う場合には「アダプター」パターンがよく使用されます。これらのデザインパターンに興味がある方は、書籍や各リンク先のページをご覧いただくと良いでしょう。
最後に
本稿ではDDDにおけるファクトリについて紹介しました。オブジェクト生成を担当するシンプルな考え方ですが、設計指針や生成パターンがあることが理解できたと思います。次回の第12回ではDDDの「リポジトリ」について紹介します。
参考資料
- Factories パターン:コンストラクションは分離せよ(増田さん)
- コードで学ぶドメイン駆動設計入門 ~ファクトリ編~(かとうさん)
- C# 4.0で実装するデザインパターン「その1 生成に関するパターン」(かずきさん)
- 矢沢久雄の早わかりGoFデザインパターン(2) Iteratorパターン/Adapterパターン
- 矢沢久雄の早わかりGoFデザインパターン(3) Factory Methodパターン/Abstract Factoryパターン
- 矢沢久雄の早わかりGoFデザインパターン(5) 第5回 Builderパターン/Prototypeパターン
- アダプターパターン(Wikipedia)
- ACID特性(アトミック性について)(Wikipedia)
