たなかこういちの開発ノート

システム開発に携わる筆者が、あれこれアウトプットするブログ

「サブジェクト指向」について(私的実践DDD、その4)(2 of 2)

(※前回からの続きです。)
 
サブジェクトにおいてリポジトリーと集約はいかなる構造を取るか?
 
ここまでで次のような疑問を持たれた方もいらっしゃるでしょう。
 
『サブジェクトの捉え方は理解したとして、その場合集約やリポジトリーはどのように設計されるのか?先の「受注」でいえば、「注文受付オペレーションサブジェクト」と「販売管理サブジェクト」それぞれが固有の集約やリポジトリーを持つのか?それとも一つの集約やリポジトリーを共有するのか?各サブジェクトそれぞれが持つなら、両者間の一貫性維持をどう実現すればいいか?一つを共有するなら「境界付けられたコンテキスト」をそもそも侵してないか?』
 
これには次の二つの解法があると考えます。
 
一つ目は、各サブジェクトを、まさにマイクロサービス(Microservice)として実装する方式です。「注文受付オペレーションサブジェクト」と「販売管理サブジェクト」それぞれをマイクロサービスとして実装します。各サブジェクトそれぞれに実際に固有の型の「受注」エンティティ(もしくは集約)を設けます。二つのエンティティ(もしくは集約)間の一貫性はイベント通知で相互にデータ交換するかたちのEventually Consistency(結果整合性)なBASEトランザクションで実現します。
 

f:id:tanakakoichi9230:20150803110445p:image

図7.サブジェクトの集約/リポジトリーを、マイクロサービス方式で実装する場合
 
方式としては全く全うです。マイクロサービスの考えを適切に適用した実現方式でしょう。ただ、二つのサブジェクトに双方向の依存性がある場合、業務のプロセスが二つのサブジェクトのユースケースが交互に呼び出されることで進行するような場合、つまるところ実態的に疎結合ではないにもかかわらず、マイクロサービス分割するのは、システムに不適当な複雑さをもたらす様に思えます。
 
二つ目は、永続化層、具体的にはRDBのテーブルなどですが、これを共有することとします。しかし、O/Rマッパーのレベルで、サブジェクト毎に異なるマッピングをします。例えば、「注文受付オペレーションサブジェクト」における「受注」エンティティ(もしくは集約)では、項目「納品予定日」のマッピングを行いません。「販売管理サブジェクト」における「受注」エンティティ(もしくは集約)では、項目「納品予定日」のマッピングを行ないます。リレーションも異なるかもしれません。「注文受付オペレーションサブジェクト」においては、集約ルートは「受注」のヘッダー部エンティティとなる一方、「販売管理サブジェクト」においては、集約ルートは「受注明細」エンティティとなっているかもしれません。
 

f:id:tanakakoichi9230:20150803110435p:image

図8.サブジェクトの集約/リポジトリーを、同一RDBからの異なるO/Rマッピングで実装する場合
 
O/Rマッピングが異なるということは、各サブジェクトはエンティティもしくは集約について異なるモデルを描いている、ということを意味します。というよりも、各サブジェクトがエンティティもしくは集約について異なるモデルを描いている故に、O/Rマッピングが異なるわけです。各サブジェクトが、一見同一のデータ種と思えるエンティティもしくは集約に異なるモデルを想定するのはまさに「サブジェクト指向」の表れです。しかし、RDB上に構築されている“リレーショナル・モデル”は共有、共用します。
 
 
二つ目の解法はなかなか興味深いです。サブドメインのモデルは、集約の構造として描かれます。集約は一般にORMでRDBにマップされます。この点をよく分析してみます。まず、OOによってモデル表現されているがそれはRDBによって“裏打ち”されていて、その“裏打ち”をDDDでは「階層アーキテクチャーにおける基盤層」と表現している、ということを思い出してみます。次に、このことを逆から見ると、RDBの存在は基盤層の実装詳細だとして、DDDによるモデリングの対象には含まれていない、ということに気付きます。つまり、基盤層たるRDBに構築されている“リレーショナル・モデル”を如何に取り扱うべきかDDDに言及はないのです。
 
そこで、リレーショナル・モデルの取り扱いについて一つ提案をするわけです。「関連するサブジェクト間ではリレーショナル・モデルを共用するが、サブジェクト毎に適切な、それぞれに異なるO/Rマッピングを行ってみよう」、と。
 

f:id:tanakakoichi9230:20150803110456p:image

図9.DDDのスコープ
 
各サブジェクト(のモデル)は、ひとつのリレーショナル・モデルの様々な“プロジェクション”と捉える
 
RDBに構築されるリレーショナル・モデルを、しかもDDDのスコープ外に存在するようなものを、ある種本質的な存在とみなすことに抵抗があるでしょうか?正規化されたリレーショナル・モデルからは、どのような“ビュー”をも生成できます。この点はリレーショナル・モデルの理論上完全です。O/Rマッピングとは、結局のところ一つ特定のビューを設けることに他なりません。いかなるビューをも設けられるということは、いかなるO/Rマップをも可能だということで、つまり、一揃えのリレーショナル・モデルは、いかなるOOモデルにも適合させることができるということです。一式のリレーショナル・モデルから、どのようなエンティティを集約ルートにしたかたちのマッピングも可能だし、項目を取捨選択したマッピングも全く問題ありません。
 
以上の様子を、「関連する各サブジェクトのモデルは、ひとつのリレーショナル・モデルの様々なプロジェクション(Projection)である」と捉え表現することとします。
 

f:id:tanakakoichi9230:20150803110511p:image

図10.サブジェクト(OOモデル)は、一つのリレーショナル・モデルからの様々なプロジェクション
 
 
ここに「古典的OO」とサブジェクト指向の統一理論を構築することができます。一般に、一揃えのリレーショナル・モデルからは複数のプロジェクションが想定できます。各プロジェクションはそれぞれがサブジェクト、です。ここで、「古典的OO」とは、一揃えのリレーショナル・モデルからプロジェクトされるサブジェクトが、偶然にもしくは意図的にただひとつであるような、サブジェクト指向の特別なケースである、と位置付けるのです。
 

f:id:tanakakoichi9230:20150803110519p:image

図11.サブジェクト指向における古典的OO
 
加えて「CQRS(コマンド・クエリ責務分離)」をもこの統一理論に統合することができます。即ち、一揃えのリレーショナル・モデルからプロジェクトされるサブジェクトが、偶然にもしくは意図的に、更新向けに一つと参照向けに一つ設けられるような場合、それを「CQRS」と称する、と位置付けるのです。
 

f:id:tanakakoichi9230:20150803110526p:image

図12.サブジェクト指向におけるCQRS
 
 
<追記>
本文に突っ込みポイントが既に3点くらい見出されているので、まずはこのまま公開するが、追い追いupdateしたいところである。。
 
◆以上