ドメインモデルを利用するアプリケーションとは
「アプリケーション」とは、広義の意味では「システム」全体と同じ意味となりますが、本稿では、ドメインモデルを使用するクライアントである「ユーザーインターフェイス層」「アプリケーション層」について紹介します。
ユーザーインターフェイス(UI層)とは
まず、利用者が操作する「ユーザーインターフェイス層(以降UI層)」のソフトウェア例をいくつか挙げてみましょう。
- サーバー側で処理するWebシステム
- ブラウザ側で描画するWeb APIサービス
- WinFormsやSWTやSwingといったネイティブ「GUIクライアント」
- スマートフォンアプリケーション
このように、通常、利用者に使い勝手の良いユーザーインターフェイスを提供するように努めます。
アプリケーション層(アプリケーションサービス)とは
ドメインサービスとの比較で軽く紹介しましたが「アプリケーションサービス」とはアプリケーション層に存在するドメインモデルのクライアントとなります。
アプリケーションサービスの責務は、タスクの調整であり、ユースケースのイベントフローごとにメソッドを提供します。アプリケーションサービスはあくまで調整役のため、薄い処理を行うだけのレイヤーとなります。この点でビジネスロジックを持つドメインサービスと対照的と言えます。
アプリケーションサービスが調整する対象は、単一の境界づけられたコンテキストの場合もあれば、複数のコンテキストにまたがる場合もあります。またリポジトリの呼び出し例にて紹介したように、データベースのトランザクションといったコントロールを行う場合もあります。
ドメインモデルを利用するアーキテクチャ
UI層で描画するデータはドメインモデルから取得してきます。4章にて紹介した通り、ドメイン層を取り囲むアーキテクチャとしては以下のパターンが存在します。
機能やチーム状況に応じてアーキテクチャは変化しますが、基本的な方式として、UI層が、アプリケーション層の「アプリケーションサービス」を使用し、ドメインモデルを呼び出す流れとなります。
ドメイン層とUI層間における情報の受け渡し方法
まず、ドメイン層の情報をどのようにUI層に受け渡すかについて整理してみましょう。基本的に、UI層で描画するデータを取得するためには「複数の集約」の情報を組み合わせる必要があります。逆に更新操作を行う場合にはUI層で入力された値を「1つの集約」に対して更新依頼することが一般的です。
UIで描画する場合、複数の集約にアクセスして情報を取り出す必要があります。こういった情報を、UI層に受け渡す方法としてIDDD本では次の3つを挙げています。
(1)複数の集約情報をDTOへ詰め替え
有名な方法として、複数の集約の情報を「データ転送オブジェクト(DTO)」に詰め替える方法が挙げられます。この場合、まずアプリケーションサービスは、リポジトリ経由で複数の集約を取得します。次に、DTOを組み立てるクラスである「DTOアセンブラ(ValueObjectアセンブラ)を用いて、DTOに設定します。
この詰め替えを行うために、集約の保持する情報をDTOアセンブラに公開する必要があるかもしれません。これを避ける方法として、集約側に詰め替えメソッドを用意し、引数に渡されたDTO用オブジェクトへ詰め替えることも可能です。
(2)複数の集約へ参照を保持するDPOを返送
次の方法として、ヴァーノン氏が考えた「ドメインペイロードオブジェクト(DPO)」があります。ペイロードとは搭載物やデータ本体を指しますが、DPOでは集約そのものを指します。つまり、1つのDPOは複数の集約のインスタンスを保持し、レイヤー間で受け渡しします。
この方法は、設計がシンプルで、詰め替えに伴うメモリ消費が小さいメリットがあります。ただし、DPOを利用するレイヤー(UI層)にドメインモデルを公開しなければいけなくなります。また集約のプロパティに遅延ロード項目がある場合は事前にロードしておく必要があります。
(3)ユースケースに最適化したクエリによる取得
最後の方法として、ユースケースで最適化したクエリをリポジトリに用意し、値オブジェクトを返す方法があります。これは、リポジトリにファインダーメソッドを用意しておき、複数の集約を組み合わせたカスタムオブジェクトを返します。その情報を(DTOではなく)値オブジェクトに設定して返します。あくまで、ユースケースのフローに特化したDTOではなく、業務ドメインに特化した値オブジェクトを用意するアプローチとなります。
なおCQRSと似ていますが、この場合は、ユースケースに対応した処理をドメイン層に用意して、リポジトリにて最適化することを示しています。
複数クライアントに対応するための出力形式の切り替え
複数クライアントに向けた開発では、JSON形式やXML形式にて出力を分ける場合も多いと思います。こうした要望に対して、IDDD本では「データトランスフォーマ」と呼ばれる仕組みを用いて出力形式を切り替える方法を紹介しています。
例えば、カレンダーの週次情報を表示するシナリオの場合「CalendarWeekCSVDataTransformer」「CalendarWeekJSONDataTransformer」「CalendarWeekDTODataTransformer」のように欲しい形式名にて指定します。
ヘキサゴナルアーキテクチャのポート&アダプター方式であれば、1つのポートに対して、出力フォーマット別にアダプターを実装するイメージとなります。この仕組みによってクライアントは、データトランスフォーマの型を指定してアプリケーションサービスを呼び出すことで、任意のデータ形式を取得できます。