複数コンテキストの結合を緩やかにする値オブジェクト
引き続き、SaaSOvationを例に値オブジェクトの実装について見ていきましょう。複数のコンテキストを扱う場合、値オブジェクトを使うことでコンテキスト間の結合を緩くできます。
5章では、認証・アクセスコンテキストの「ユーザ」と「ロール」のエンティティ(正確には10章で紹介する集約)について検討しました。コラボレーションコンテキストでもユーザやロールと似た情報を取り扱いますが、コンテキスト間の結合を緩やかにするために「ユーザ」と「ロール」をそのまま使用せずに自分のコンテキストで必要な情報を扱う「値オブジェクト」を用意しています。具体的には「モデレーター」「オーサー」「クリエーター」「オーナー」「参加者」を値オブジェクトとして作成しています。
このような他コンテキストの「エンティティ」「値オブジェクト」「標準型」といったオブジェクトを、自コンテキストではミニマムに保とうといった考え方は、コンテキスト間の結合を緩めるために有効といえます。
区分や種類を示す標準型(タイプコード)
タイプコードとはオブジェクトの種類を示すコードで、多くのアプリケーションで利用されている概念です。ヴァーノン氏は、このタイプコード(日本語だと「区分値」が近いかもしれません)にあたるものを「標準型」と呼んでいます。
具体的なタイプコードの例を見てみましょう。ある電話番号のタイプを「自宅」「携帯」「職場」に分類するシナリオがあるとします。
上図のプログラムは難しくないと思いますが、左側のタイプコードの場合、電話番号の区分(タイプ)が数値型(int)のため、0~2以外の範囲外である値が設定されてしまう恐れがあります。そこで、ファウラー氏の書籍「リファクタリング」では「クラス(もしくはサブクラス、もしくはState/Strategy)によるタイプコードの置き換え」といった手法で、タイプコードをなくすことを提示しています。しかし、これらの手法は作成するクラス数が多いため実装が複雑になりがちです。そこでヴァーノン氏は、このような区分において、列挙型(enum)の使用を強く推奨しています。上図の右側がenumを用いて標準型を実装した例となります。
列挙型(enum)で標準型を実装
列挙型は少ないコードで区分値を取り扱える機能を備えています。Javaでは列挙型にメソッドを書くことができるため、コードに応じた描画文字への取得や、状態に応じた処理の振り分けも列挙型の1カ所で実装できます(C#では拡張メソッドを用いて列挙型に処理を追加できます)。このように列挙型を用いることで、境界づけられたコンテキストごとに異なる標準型機能をシンプルに管理できます。
値オブジェクトで標準型を実装
別のパターンとして通貨のケースを考えてみましょう。通貨単位には円、米ドル、ユーロなどさまざまな通貨種別があることが想像できます。これらはマスタデータとして、システム全体で共有される不変の値となります。この場合、列挙型でコーディングする以外に、永続化層(DB)からデータを取得して値オブジェクトに展開する手法も存在します。
上図では標準型を列挙型ではなく、対応する値オブジェクトとしてコーディングし、それぞれの通貨型の概念を複数のインスタンスとして表現しています。
ここまでを簡単にまとめると、コンテキストの中に存在するオブジェクトとしては、エンティティ、値オブジェクト、標準型(列挙型もしくは値オブジェクトで実装)といったパターンがあることを確認できました。標準型や値オブジェクトを活用し、コンテキスト同士の結合が最小になるミニマリズムな設計を意識するといいでしょう。