腐敗防止層

レガシーシステムと新システムなど、データモデルや用語の異なるシステムの間に変換層を設け、一方の設計を汚染から守るパターン

DDD設計パターン

腐敗防止層とは

腐敗防止層 (Anti-Corruption Layer, ACL) は、Eric Evans が DDD で提唱したパターンで、データモデルや用語の異なるシステムの間に変換層を設け、一方の設計を他方の影響から守る。例えば、レガシーシステムから新システムへ段階的に移る間の連携に使う。

なぜ必要か

レガシーシステムと新システムを直接接続すると、レガシー側のデータモデルや命名規則が新システムに漏れ出し、設計を汚染しうる。ACL を間に挟むと、新システムは自身のドメインモデルを保ったまま、レガシーと連携できる。一方で、層の分だけ呼び出しの遅延が増え、管理と保守の対象も 1 つ増える。

問題説明
レガシーのデータモデルが汚い新システムに不要なフィールドが混入
API の互換性レガシーの API 変更が新システムに波及
用語の不一致レガシーの customer と新システムの user
段階的移行一度に全て置き換えられない

ACL の構造

下の図の例では、ACL は新システムとレガシーシステムの間に位置する変換層である。レガシー側のデータモデルを受け取り、新システムのドメインモデルに変換してから渡す。逆方向も同様に、新システムのモデルをレガシーが理解できる形式に変換する。

新システム → [ACL (変換層)] → レガシーシステム
              ↑
  レガシーのデータモデルを
  新システムのドメインモデルに変換

TypeScript での実装

下の toOrder は、レガシーの項目名と状態の記号を、新システムのドメインモデルの名前と値に置き換える。

// レガシー API のレスポンス (汚いモデル)
interface LegacyOrder {
  ord_id: string;
  cust_name: string;
  ord_amt: number;
  ord_stat: 'A' | 'C' | 'X';
}

// 新システムのドメインモデル (きれいなモデル)
interface Order {
  id: string;
  customerName: string;
  amount: number;
  status: 'active' | 'completed' | 'cancelled';
}

// ACL: レガシー → ドメインモデルに変換
function toOrder(legacy: LegacyOrder): Order {
  const statusMap = { A: 'active', C: 'completed', X: 'cancelled' } as const;
  return {
    id: legacy.ord_id,
    customerName: legacy.cust_name,
    amount: legacy.ord_amt,
    status: statusMap[legacy.ord_stat],
  };
}

ACL vs アダプター

観点ACLアダプター
目的ドメインモデルの保護インターフェースの変換
スコープ境界づけられたコンテキスト間モジュール間
出自DDD で定義された概念GoF のデザインパターン

いつ使うか

変換層を立てるかどうかは、相手のデータモデルを自分たちのドメインに持ち込みたくないかどうかで決まる。

場面判断理由
レガシーシステムと統合する挟む相手の命名や不要なフィールドが新システムへ流れ込むのを減らし、customer と user のような用語の不一致を変換層の中で解消できる
旧システムを段階的に置き換える挟む移行が完了するまで両方のモデルが併存するため、対応表を変換層に集めておくと、切り替え時に消す範囲を見通しやすい
仕様を自分たちで決められない外部 API を使う挟む相手側の API 変更の影響を変換層で受け止め、ドメインモデルと呼び出し側のコードへの波及を減らせる
同じシステム内のモジュール同士をつなぐ挟まない境界づけられたコンテキストをまたがず双方を直せるので、インターフェースを合わせるアダプターで足りる

現場での応用を知るには関連書籍も役立つ。

共有:

この記事は役に立ちましたか?

関連用語

関連する記事