---
# System prepended metadata

title: Untitled

---

## 第14章 モデルの整合性を維持する　p.361～p.387

### 境界づけられたコンテキスト間の関係 p.361
このあとに議論するパターンによってカバーされる様々な戦略は、2つのモデルを関係づけるためのもの
目的：
1. 開発作業をうまく構成できるようにするための目標を与えること
2. 既存の構成を記述するための語彙を提供すること

以下は2つのモデルを関連付けるためのパターン例

#### 共有カーネル（SHARED KERNEL） p.361
モデル・コードベース全体でなく、慎重に選択したサブセットを2つのチーム間で同期する

継続的な統合を維持するためのスキルや政治的組織が
- チームにない
- 1つのチームとしてとにかく大きすぎて扱いにくい場合
別の境界づけられたコンテキストが定義され、複数のチームが編成される

こうしたまとまりのない複数のチームが密接に関連したアプリケーションを開発すると、当初はうまくいくがやがてそれぞれが作り出す物はうまく適合しなくなる。結果的にはじめから継続的な統合を行った場合よりも時間がかかってしまう（変換層の作成とか）。共通のユビキタス言語を持つ利点も失ってしまう。

2つのチームが共有することに合意したドメインモデルのサブセットを指定すること（モデルのサブセット・モデルの該当箇所に関連するデータベース設計を含む）。
- もう一方のチームに相談せずに変更してはならない
- 稼働しているシステムは頻繁に統合する（チーム内で行われる継続的な統合よりは頻度を下げる）
- 統合の際には両チームのテストを実行する

通常、共有カーネルを変更する場合は、共有カーネルを別にコピーして行い時間をおいて他のチームと統合する

共有カーネルは、
- コアドメイン
- 複数の汎用サブドメインの集合
- または、その両方（15章参照）

目標 = 重複を減らして、2つのサブシステム間の統合を比較的容易にすること

#### 顧客／共有者の開発チーム（CUSTOMER/SUPPLIER DEVELOPMENT TEAMS） p.365
一方のサブシステムが、本質的にもう一方のサブシステムに対して入力を与えるものである場合
「下流」のコンポーネントが実行するのは分析、や「上流」のコンポーネントにほとんどフィードバックを与えない関数で、すべての依存関係は1方向になっている。
↓
上流・下流は2つの境界づけられたコンテキストに自然に分かれる

上流：下流が作り出す物に対して責任を持たない
下流：上流から来るものを必要とする
この場合、チーム間の関係を形式化すれば誰もが楽になる（政治的な駆け引き等を発生させない）

エクストリームプログラミングのイテレーションプランニングプロセスがその仕組みとして使える
下流のチームの代表＝ユーザーの代表と同じような役割でプランニングに参加させる
上流のイテレーション計画は、下流チームが最も必要とする作業を含むか、合意によって作業が延期される（納品を待つ必要がなくなる）
↓
- 2つのチームに明確な顧客／供給者という関係を確立すること
- 計画時に下流の要件に必要となる作業について交渉し、予算を立てることで提供の約束とスケジュールを全員が理解できるようにする
- 期待されるインターフェースを検証する、自動化された受け入れテストを共同で開発すること
    - 上流チームのテストスイートに追加し、継続的な統合の一部として実行されるようにすること（下流への副作用を心配せずに自由に変更を行えるようになる）

顧客と供給者の関係＝顧客の要求が最優先（ただし、下流のみが顧客ではないので様々な顧客の要求は交渉の中でバランスをとる必要がある）

##### 例14.3 収益分析と予約
会社が受けつけた予約をすべて分析して、どう収益を最大化するかを調べるプロジェクト
明らかな境界づけられた2つのコンテキスト（別々の実装ツール・別々のドメインモデル）
- 予約アプリケション（上流）
- 分析ソフトウェア（下流）
共有カーネルは適さない（異なる実装技術が使われているため）
予約アプリケーションには収益分析に対する依存関係がない
お互いのチームに協力関係があったため（副社長が報告相手だとか・2つのチームのプロマネが仲がよいとか）、顧客／共有者の開発チームを適用できた
↓
顧客／供給者チームのパターンが成功するためには、以下の2パターン
- 2つのチームが同じ経営陣の下にいて、最終的な目標を共有できる場合
- 実際に顧客／供給者の関係である別々の企業の場合である

上流チームの動機付けあることが必須

#### 順応者（CONFORMIST） p.370
2つの開発チームに上流/下流関係があるにも関わらず、上流に下流チームの要求に応える動機がない場合、下流チームはどうすることもできない。

この状況での考えられる選択肢は3つ
1. 上流の機能を使用するのを一切断念する
    - 別々の道へ

1が様々な理由で許されない場合(上流のソフトウェアを使用することの価値が非常に高い or 政治的な理由)、

2. 上流の設計を扱うのが難しすぎる場合（カプセル化の欠如・ぎこちない抽象・下流チームでは使用できないパラダイムを用いたモデリング）、独自のモデルを開発する必要がある
    - 腐敗防止層へ
3. 設計の品質がそれほど悪くなく、スタイルもそれなりに互換性がある場合は、独立したモデルを完全に断念する
    - 順応者（この項）

上流チームのモデルに隷従することで生じる、境界づけられたコンテキスト間での複雑な変換を取り除くこと。
- 順応することで統合は大幅に簡略化される
- ユビキタス言語を共有する
- 下流の設計者がとれるスタイルは制限される
- 理想的なモデルは作ることができなくなる

上流への依存関係は深くなり、アプリケーションの可能性は上流モデルに今ある能力と純粋に付加的に行われる機能追加によって制限される。

このやり方が気に入らない場合は腐敗防止層を使う選択肢もある

共有カーネルとの類似点
- どちらにも同じモデルを持つ重なり合う領域と、付け加えることで自分のモデルが拡張される領域、それに、他のモデルによる影響を受けない領域がある

異なっている点
- 意思決定と開発プロセス
    - 共有カーネル：密接に協力し合う2つのチームによる共同作業
    - 順応者：共同作業に興味がない

#### 腐敗防止層（ANTICORRUPTION LAYER） p.373
変換層：うまく設計された境界づけられたコンテキスト同士を協力的なチームで橋渡しする場合に機能する

隔離するためのレイヤを作成することによって、クライアントに対して、独自のドメインモデルの用語で表現された機能を提供すること。この層は、既存のインターフェースを通して他のシステムと通信するので、他のシステムを修正する必要はほとんどないか、全くないこともある。内部的には、このレイヤが必要に応じて、2つのモデル間での変換を両方向に対して行う。

腐敗防止層：他のシステムへメッセージを送信する仕組みではなく、あるモデルやプロトコルの持つ概念オブジェクトやアクションを、別のものに変換する仕組み

##### 腐敗防止層のインスタフェース
- 通常はサービスの集合
- まれにエンティティのかたちをとる

##### 腐敗防止層の実装
[ファサード](https://www.techscore.com/tech/DesignPattern/Facade)と[アダプタ](https://www.techscore.com/tech/DesignPattern/Adapter/)および変換サービスを組み合わせ、システム間の通信に通常必要となるコミュニケーションと転送の仕組みと組み合わせて使う

- ファサード
    サブシステムのための代替インターフェース。クライアントのためにアクセスを簡略化して、サブシステムを使いやすくする
    基盤となるシステムのモデルを変更しない
    他システムのモデルに厳密に従って作成する（そうしないと変換の責務が複数オブジェクトに拡散してしまう）
- アダプタ
    ふるまいを実装している側が理解している物とは別のプロトコルをクライアントが使えるようにするためのラッパ
    アダプタの仕事＝他のシステムへのリクエストをどうやって作成するかを知ること
    2つのモデル間の変換
- 変換サービス
    概念オブジェクトやデータを実際に変換する。変換サービスはアダプタに属する

あまりにも変換に負担がかかる場合は順応者パターンも考慮に入れる

腐敗防止層は2つの境界づけられたコンテキストを連結する手段である
- 普通は、自分のシステムと他の人が作ったシステムとの連結の場合が想定される。相手方のシステムに関する理解は不完全であり、コントロールすることはほとんどできない。
- 自分で作ったサブシステム同士が別々のモデル似基づいている場合は、腐敗防止層でつなぐことに意味がある

##### 例14.4 レガシー予約アプリケーション
レガシーシステムと新しいアプリケーションの橋渡しとしての腐敗防止層
分離することで新しいアプリケーションをレガシーアプリケーションから独立して開発できるようになる（ただし、腐敗防止層の変換に投資が必要）
レガシーの機能を引き継ぐことも既存の機能を引き継がずに新しい価値を追加するだけにとどめることもできる

##### 訓話
どんな統合にもオーバーヘッドはつきもので、有益かもしれないが必ず高くつくのでそれが本当に必要かは確かめなければならない。

#### 別々の道（SEPARATE WAYS） p.380
要件は容赦なく調べ尽くされなければならない。
その上で、2つの機能の集合が互いにとって不可欠でないのなら、切り離すことができる。

統合は常に高くつくが、それによる利益は小さいこともある。

ユースケース上で機能が関連しているというだけでは、統合が必須であるということにはならない。

境界づけられたコンテキストを他とは一切つながりを持たないものと宣言し、開発者がその小さいスコープ内で、シンプルに特化した解決策を見つけられるようにすること。

それぞれの機能をミドルウェアやユーザインターフェース層においてまとめることはできるが、ロジックを共有することはない。変換層を通じてのデータ転送は最低限に抑えるか、ないほうが望ましい

##### 例14.5 保険プロジェクトの縮小化
顧客サービスの代理人や保険査定人が必要とするものをすべて1つのシステムに統合しようとしていたが行き詰まった
↓
1. 要件の一覧を作成
2. 難易度を見積もって重要度を割り当てた
3. 難しくて重要でないものは切り捨て
4. 残りの一覧に順番をつけた
5. 最終的に重要だと判明したのは1つの要件だけ
↓
統合してもほとんど付加価値を生まない機能があるという認識を得た
↓
同一メニューから起動する小さい複数のプロジェクト（それぞれは統合しない）

別々の道に進む = 完全に分離して開発した複数のモデルをマージさせるのは困難

#### 公開ホストサービス（OPEN HOST SERVICE） p.383
各境界づけられたコンテキストにおいて、コンテキストの外にある統合すべき各コンポーネントに向けた変換層を定義する = 1回限りの統合なら低コストでモデルの崩壊が回避できる

統合に際して、それぞれに特別な変換サービスを作成すると、保守するべきものが次第に大きくなっていき、変更を行う際に注意すべきことも次々と増える。
↓
サブシステムにアクセスできるようにするプロトコルを、サービスの集合として定義すること。そのプロトコルを公開し、こちらのサブシステムと統合する必要のある人が全員使用できるようにすること。新しい統合の要件に対応する際には、プロトコルに機能を追加し、拡張すること。ただし、あるチームだけに特有の要求は別だ。そのような特殊なケースには、1回限りの変換サービスを使用してプロトコルを拡張し、共有プロトコルは単純で一貫性のある状態に保つこと。

通信を形式化する = モデル語彙を共有する
モデル語彙 = サービスインターフェースの基礎となるもの

#### 公開された言語（PUBLISHED LANGUAGE） p.384
2つの境界づけられたコンテキスト内にあるモデル同士では、共通の言語が必要である

既存のドメインモデルへの直接的な変換や、既存のドメインモデルからの直接的な変換は、適切な解決策でないことがある。既存のモデルは過度に複雑であったり、うまく分割されていなかったりするかもしれない。おそらくは、ドキュメント化されてもいない。そのモデルをデータ交換用の言語として使ってしまうと、本質的に動きが取れなくなり、新しい開発の要求に対応できなくなる。

- 標準化されたプロトコルを使用する
- すでに公表されている言語を探す
    公表 = その言語を使用することに関心のあるコミュニティが、いつでもその言語を入手できる状態にあり、それぞれの解釈が互換性を保つようにドキュメント化されている

↓

必要なドメインの情報をコミュニケーションにおける共通の媒体として表現できる、明確にドキュメント化された共通言語を使用し、必要に応じてその言語への変換と、その言語からの変換を行うこと

こうした言語はいちから作成しなくても、すでにドキュメント化された物があるならそれを利用する事ができる

##### 例14.6 科学のための公表された言語
- 化学式のカタログ、分析、操作のために無数のプログラムがあり、別々のモデルを使っているため、それぞれのデータ交換が難しかった
- CML = 科学マークアップ言語：XMLの方言。このドメインの共通交換言語となるように意図された。学会と業界を代表するグループによって開発・管理されている
- XMLを使うことで
    - 学習曲線が平坦化
    - パーサなどの既存ツールが使えるので実装が容易になった
    - ドキュメント化も楽になった


