ファクトリとは
開発における一般的な「ファクトリ」とは、複雑になりがちなオブジェクト群を簡単に組み立て、呼び出し側に対して内部構造を隠して生成する仕組みのことを指します。これに対して、DDDのファクトリでは「ユビキタス言語を用いて集約をシンプルに生成する」という意味合いが強くなります。そのためDDDのファクトリとしては、下記のようなシナリオが中心となります。
- 特定の集約にて、別のオブジェクト(主に集約)を生成
- サービスにて、別の「境界づけられたコンテキスト」のオブジェクトを、ローカルの「境界づけられたコンテキスト」の型のオブジェクトに変換して生成
一般的なプログラミングパターンでもオブジェクトを生成するという意味合いは同じですが、DDDの場合は、ユビキタス言語にて業務を表現し、見せるべきでない情報を保護し、整合性のとれた集約を生成します。
ファクトリを使う理由
ファクトリを使う理由として、IDDD本では、エヴァンス氏の次の説明を引用しています。
複雑なオブジェクトと集約のインスタンスを生成する責務を、別のオブジェクトに移すこと。その別のオブジェクトは、それ自体ではドメインモデルにおいて何の責務も負っていないかもしれないが、それでもドメイン設計の一部であることに変わりはない。
エヴァンス氏は、「車のエンジン」や「銀行口座」を例にファクトリを利用する理由を紹介しています。エンジンの場合「複数部品を使ってエンジンを組み立てたてる処理」と「回転する処理」を分けています。銀行口座の場合「口座の開設処理」と「口座の取引処理」を分けています。このように複雑な生成処理を分離することで、全体を理解しやすくできることがファクトリのメリットと紹介しています。
IDDDにおけるファクトリの例
IDDD本においては、別の集約にファクトリメソッドを用意する方法を主に紹介しています。つまり「ファクトリ」は「集約の振る舞い(メソッド)」となります。
SaaSOvationでは「ユーザー」を生成するために、「テナント」集約に「ユーザーを登録する」というファクトリが存在しています。このメソッドを呼び出すと、テナントの情報とクライアントから渡された引数の情報を使用して「ユーザー」が生成されます。そして(そのオブジェクトを「テナント」集約に保持するのではなく)呼び出し側のクライアントに返します。
ファクトリの設計
ここからはオブジェクトの生成のパターンについて見ていきましょう。まずオブジェクトを生成する場合、クライアント側からコンストラクタを呼び出すという単純なケースが考えられます。これを含めると、オブジェクトの生成パターンとしては、次の3パターンが想定できます。
IDDDでのファクトリの種類 | メソッドの場所 | メソッド名 | 特徴 |
---|---|---|---|
(1)コンストラクタ | クラス本体 | クラス名 |
コンストラクタのためシンプル。ユビキタス |
(2)集約上のファクトリ | 集約 | ユビキタス言語 |
複雑な生成が可能。不変条件を満たしたり、 引数を減らしたりすることができる。 |
(3)サービス上のファクトリ | ドメインサービス | ユビキタス言語 | 境界づけられたコンテキスト間の変換が可能。 |
これらの特徴について順番に紹介していきましょう。