イベントを連携する「Notification(通知)」の仕組み
DDDで外部の境界づけられたコンテキストに情報を連携するには、8章で紹介した「イベント」を使用できます。IDDDでは、このイベントを「Notification(通知)」という仕組みを用いて連携します。RESTfulサービスで公開される場合もあれば、RabbitMQのようなメッセージング基盤を用いて連携される場合もあります。
「イベント」を格納するNotificationクラス
「Notification(通知)」クラスは、さまざまな種類の「イベント」を格納できます。このクラスでは、格納するイベントの型を示す情報を「typeName」に、イベントの詳細情報を「Event」に設定します。これらの仕組みにより、さまざまなイベントを境界づけられたコンテキスト間で連携することができます。
「イベント」を読み出すNotificationReaderクラス
IDDDでは、NotificationReaderという通知に対する読み取り専用のクラスを用意しています。このクラスを利用することで「reader.eventDateValue("/occurredOn"));」のようなXPath風の構文や「reader.eventStringValue("tenant.id");」のようなドット区切り構文にて、イベント情報を簡単に読み取ることができます。
このNotificationReaderクラスでは「event{String/Boolean/Date/Double/Float/Long}Value」メソッドにて値を読み出すことができます。この時、Nullのように、値が取れない場合でもエラーではなく空白や適切な値が戻されるようになっています。そのため、イベントの定義が変わった場合にも、安心して既存のバージョンを使い続けることができます。
コンテキスト間における連携アーキテクチャ
境界づけられたコンテキストの統合を行う場合、大きく次の3つのアーキテクチャパターンが存在しています。
- (A)RPC方式:コンテキストAにて操作APIを公開し、コンテキストBから呼び出す
- (B)RESTful方式:コンテキストAにてリソースを公開し、コンテキストBから呼び出す
- (C)メッセージング方式:コンテキストAからメッセージを配信し、コンテキストBにて取得する
RPC方式はDDDに限らず以前から利用されているので、本稿では(B)RESTful方式の2パターンと(C)メッセージング方式の3パターン(計5パターン)を紹介します。
RESTfulリソースを用いた統合アーキテクチャ
まず、RESTful方式について紹介していきます。4章のアーキテクチャにて紹介した通り、RESTfulなシステムではリソースに対するリクエストをHTTPメソッド(GET/PUT/POST/DELETE)を用いてアクセスする方法となります。
(1)RESTfulリソースを用いた統合(リアルタイム連携)
最初のパターンとして、RESTサービスを情報が必要な時に呼び出す方式について見ていきましょう。下図のシナリオでは、ユーザーがどのような権限を持つか知りたい場合に、「認証・アクセスコンテキスト」のRESTサービスに問い合わせをしています。そして、取得結果のJSON情報を元に、腐敗防止層で「コラボレーションコンテキスト」の投稿者/作成者/モデレーター/所有者/参加者に変換しています。
ポイントとしては、ユースケース(利用シナリオ)を元にRESTの設計をしていることです。「認証・アクセスコンテキスト」では「ユーザー」の情報を保持していますが、それらをすべて公開するのではなくユースケースに必要なモデルのみRESTサービスにて公開しています。
(2)RESTfulリソースを用いた統合(バッチ/タイマー連携)
上記の方式の場合、リアルタイムで情報を取得できるメリットがありますが、リモート側の「認証・アクセスコンテキスト」にてトラブルが発生した場合、ローカル側の「コラボレーションコンテキスト」でも大きな障害になる危険性があります。そこで、リアルタイムにリモートサービスを呼び出すのではなく、非同期にてリモート側のイベントを取り込むパターンを見ていきましょう。
リモート側の「認証・アクセスコンテキスト」でユーザーに変更があった場合、集約からイベントを生成し、イベントストアに情報を蓄積していきます。そして、その情報をNotificationのRESTサービスとして公開します。「コラボレーションコンテキスト」側では、会員情報変更のイベントを都合の良いタイミングで取り込み、結果整合性を保つことができます。