腐敗防止層
レガシーシステムと新システムの間に変換層を設け、新システムの設計を汚染から守るパターン
DDD設計パターン
腐敗防止層とは
腐敗防止層 (Anti-Corruption Layer, ACL) は、Eric Evans が DDD で提唱したパターンで、レガシーシステムと新システムの間に変換層を設け、新システムの設計をレガシーの影響から守る。
なぜ必要か
レガシーシステムと新システムを直接接続すると、レガシー側のデータモデルや命名規則が新システムに漏れ出し、設計を汚染する。ACL を間に挟むことで、新システムは自身のドメインモデルを純粋に保ったまま、レガシーとの統合を実現できる。
| 問題 | 説明 |
|---|---|
| レガシーのデータモデルが汚い | 新システムに不要なフィールドが混入 |
| API の互換性 | レガシーの API 変更が新システムに波及 |
| 用語の不一致 | レガシーの customer と新システムの user |
| 段階的移行 | 一度に全て置き換えられない |
ACL の構造
ACL は新システムとレガシーシステムの間に位置する変換層である。レガシー側のデータモデルを受け取り、新システムのドメインモデルに変換してから渡す。逆方向も同様に、新システムのモデルをレガシーが理解できる形式に変換する。
新システム → [ACL (変換層)] → レガシーシステム
↑
レガシーのデータモデルを
新システムのドメインモデルに変換
TypeScript での実装
TypeScript での実装のコード例を示す。
// レガシー 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 とアダプターの違いを以下にまとめる。
| 観点 | ACL | アダプター |
|---|---|---|
| 目的 | ドメインモデルの保護 | インターフェースの変換 |
| スコープ | 境界づけられたコンテキスト間 | モジュール間 |
| DDD | ✅ DDD の概念 | GoF のパターン |
いつ使うか
いつ使うかの判断基準を以下にまとめる。
| ケース | 推奨 |
|---|---|
| レガシーシステムとの統合 | ✅ ACL |
| 段階的なマイグレーション | ✅ ACL |
| 外部 API との統合 | ✅ ACL |
| 内部モジュール間 | アダプターで十分 |
現場での応用を知るには関連書籍も役立つ。
この記事は役に立ちましたか?
関連用語
アダプターパターン
互換性のないインターフェースを変換し、既存のコードを変更せずに連携させるデザインパターン
境界づけられたコンテキスト
ドメインモデルが一貫した意味を持つ範囲を明確に区切り、モデルの曖昧さを排除する DDD の戦略的パターン
ドメイン駆動設計 (DDD)
ビジネスドメインの知識を中心に据え、ドメインエキスパートと開発者が共通言語で協働しながらソフトウェアを設計する手法
システムコール
ユーザー空間のプログラムが OS カーネルの機能を呼び出すインターフェース
Strangler Fig パターン
レガシーシステムを段階的に新システムへ移行する設計パターン
貧血ドメインモデル
ドメインオブジェクトがデータのみを持ち、ビジネスロジックが外部のサービスに散在するアンチパターン