DDD
担当:佐藤匡剛
ANTICORRUPTION LAYER (p.364-370) †
要約 †
ANTICORRUPTION LAYER (腐敗防止層)
(photo by Brian Kelley)
【文脈の説明】
- 新しいシステムは、たいてい他のシステムと統合しなければならない。BOUNDED CONTEXTの外側からモデルが浸食してくるような場合には、より防衛的な変換層を作らなければならないこともある。
***
【問題サマリ】
- 新しいシステムが他システムとかなり緊密に連携している場合、2つのドメインモデル間のマッピングが難しく、場当たり的な形で他システムのモデルの影響を受けてしまうことがある。レガシーシステムのモデルはイマイチだったり、そうでなくても新システムの用途には合わないことが多い。それでもシステム間統合にはメリットがあり、やらなければいけないこともある。
【問題の解決方法についての説明】
- そもそもシステム間統合しなければいい、というのは答えにならない。既存システムと連携するというのは、再利用のやり方の1つである。また大規模プロジェクトでは、システムはたいてい異なるドメインモデルをもった複数のサブシステムからなるので、システム間のインタフェースをもつことは避けられない。
- 外部システムとの連携には、多くのハードルがある。プラットフォームやプロトコルの異なるシステムと対話しなければいけないし、データ型の変換もしないといけない。しかし、中でもドメインモデルが同じでないということが重要なハードルだ。
- データを誤って解釈すれば、間違いなくエラーを引き起こす。プリミティブなデータとして見れば意味は同じでも、データをどう関連付けるかというところに、システム毎の重要な違いがある。プリミティブなデータだけを扱う低レベルのインタフェースでは、そうした知識を表現できない。
- モデルが他のモデルの断片によって壊されないようにするための、変換を提供する必要がある。
Therefore:
【解決方法サマリ】
- 隔離層を設けて、新システムのドメインモデルを守る。他システムの既存インタフェースは変更する必要はなく、隔離層にて両者のモデルの変換を行う。
***
【結果、実装上の検討事項、サンプル】
- システム間通信の技術的な話もすぐ後でするが、ANTICORRUPTION LAYERは単なる通信メカニズムだと勘違いしないように。ANTICORRUPTION LAYERは、むしろ概念的なオブジェクトや動作をモデル間で変換するためのメカニズムである。
- ANTICORRUPTION LAYERを作るのは、それ自体かなり複雑だ。以下で、その設計上の課題を検討する。
Designing the Interface of the ANTICORRUPTION LAYER (ANTICORRUPTION LAYERのインタフェース設計) †
- ANTICORRUPTION LAYERのインタフェースは通常SERVICEだが、ENTITYであってもいい。変換の責務をもった新しい層を導入することで、他システムを自分たちのモデルに合わせて再抽象化する機会が生まれる。自分たちのモデルの中では、他システムは1コンポーネントにすらならないこともあれば、複数のSERVICE(またはENTITY)で表現した方がいいこともある。
Implementing the ANTICORRUPTION LAYER (ANTICORRUPTION LAYERの実装) †
- ANTICORRUPTION LAYERの設計方法の1つは、FACADEパターン+ADAPTERパターン+変換処理、それに通信と転送の仕組みを付け加えたものだ。
- 複雑でこんがらがったインタフェースをもつシステムと統合しなければいけないことも多いが、これは実装の問題であってANTICORRUPTION LAYER本来の概念モデルの違いの問題ではない。実装の問題には、FACADEを使って対処する。
- FACADEでは、必要な機能へのアクセスだけを提供し、後は隠す。FACADEは外部システムのモデルに従って作る。FACADEにモデル変換までやらせるのは、責務の持たせすぎ。FACADEは他システムのBOUNDED CONTEXTに属している。
- ADAPTERは、あるプロトコルを別のプロトコルへと変換するラッパー。GoFのADAPTERは、オブジェクトのインタフェースを適応させるパターンだが、ここではもっと緩い意味で使っている。
- SERVICE毎にその内部にADAPTERを作り、外部システムのFACADEのインタフェースをSERVICEのインタフェースに適応させる。(Figure 14.8参照)
- 最後の要素の「変換処理(translator)」は、概念的なオブジェクトやデータを実際に変換する役割をもつ。ADAPTERの役割は、FACADEにリクエストを投げるだけ。変換処理はそれぞれのADAPTERに属する。
- ANTICORRUPTION LAYERを作る時の基本要素は上記の通り。以下は、その他の検討事項。
- Figure 14.8では自システム側がアクションの起点になっているが、ANTICORRUPTION LAYERは双方向にしてもよい。通常は外部システムの修正は必要ないが、双方向にする場合は修正が必要になる可能性もある。
- 外部システムが別サーバにある場合は、何らかの通信メカニズムが必要。この場合、どこでその通信処理をやるかを決めないといけない。
- 外部システムにアクセスする手段が何もない場合は、FACADEと外部システムとの間で通信を行う。
- 外部システムにFACADEを持たせられる場合、ADAPTERとFACADEとの間で通信を行う。
- ANTICORRUPTION LAYERを完全に外部システムに持たせることができる場合、自システムとANTICORRUPTION LAYER側のSERVICEとの間で通信を行う。
- もし自分が外部システムを修正する権限をもっているなら、外部システムのインタフェースを少しリファクタリングしてしまうともっと幸せになれるかも。
- システム間統合の要求が広範にわたる場合は、コストが跳ね上がるので、モデルを外部システムのものに合わせる必要があるかもしれない。ただし、妥協が必要な部分だけを慎重に行うこと。ほとんどのモデルを妥協しなければならないなら、CONFORMISTパターンに切り替えること。
- 外部システムが単純か、インタフェースがきれいな場合は、わざわざFACADEを作る必要はない。
- その2システム間に特有の機能であれば、ANTICORRUPTION LAYER内にそれを追加してもよい。例えば、監査証跡(audit trail)やデバッグ用の通信トレースロジックなど。
- ANTICORRUPTION LAYERは、2つのBOUNDED CONTEXTを繋ぐための手法。システム間統合は、自分が全く知らない他システムとの場合もあれば、両方とも自分たちで作ったシステムを繋ぐ場合もある。SEPARATE WAYSパターンで別々に作っちゃったシステム同士を、後から繋げる場合にもANTICORRUPTION LAYERが使える。
Example: The Legacy Booking Application (レガシーな予約アプリの例) †
- 最初のリリースを早急に行う必要があったので、変換層を通してレガシーシステムに予約処理を投げるだけの、最低限のアプリを作ることにする。自分たちのモデルを隔離するように変換層を作ったので、これはANTICORRUPTION LAYERになっている。
- ANTICORRUPTION LAYERは出荷(shipment)オブジェクトを受け取り、それを変換してレガシーシステムに渡すことで予約(booking)をリクエストする。レガシーから予約確認を受け取ったら、それを我々のモデルの確認(confirmation)オブジェクトにして戻す。これでモデルはきれいに保たれるが、この変換層を作るのは相当苦労した。
- 以降のリリースでは、レガシーの機能を新システムに引き継がせたり、まったく新しい機能を追加したり、を両システムの運用を続けながら自由に行える。この漸進的移行を可能にする柔軟さに、コストを掛けてまでANTICORRUPTION LAYERを作る価値がある。
【結果として導き出される文脈、次のパターンへの導入】
A Cautionary Tale (ある教訓話) †
- 古代中国人は、外部の遊牧民からの侵略を防ぐために万里の長城(Great Wall)を作った。万里の長城は、二千年もの間、中国の農耕文化を外敵から守った。
- しかし、長城を作るコストは莫大だったため、少なくとも1つの王朝を破綻させた。隔離戦略をどこまで徹底させるかは、コストとのバランスで考えなければならない。
- システム間統合には、常にコストがつきまとう。統合が本当に必要なのかを考えなければいけない・・・(そして次へ)
担当者のつぶやき †
- それにしても、Evansは写真チョイスのセンスがすばらしい。
- ANTICORRUPTION LAYERは、今どきだとESBとか使って構築すると良さそう。ここは非常にSOAっぽいネタ。
- ANTICORRUPTION LAYERの通信処理をどこにもたせるか、という話で、SERVICE=ADAPTER間という選択肢が出てこなかったが、なぜダメなのか? 個人的には、これが一番きれいそう。
みんなの突っ込み †
- ANTICORRUPTION LAYER の実現方法が具体的で、面白いところですよね。
>SERVICE=ADAPTER間という選択肢が出てこなかったが、なぜダメなのか?
腐敗防止層をいくつも作らない為に、Adapterの実装先でFacadeする場面もあるからかな?と思いました。でも、抽象化が過ぎると、コードを追うのが面倒なんですよねww
そんなに頑張って作った腐敗防止層自体が後年腐ってきたり・・・ -- 池田?
- すみません、「Facadeまで必要ないのでは?」と意味履き違えてました。どこをどうやったら間違えるのかww。
「SERVICEと違い、ADAPTERはPublicにならないから」という小林さんの説明で納得です。 -- 池田?