ヘキサゴナルアーキテクチャ

ポートとアダプターでビジネスロジックを外部依存から分離する設計パターン

アーキテクチャDDD

ヘキサゴナルアーキテクチャとは

ヘキサゴナルアーキテクチャは Alistair Cockburn が 2005 年の記事で示した設計パターンで、ポート (アプリケーション側が定める会話の境界) とアダプター (その境界と個々の外部技術をつなぐ変換役) によってビジネスロジックを外部依存から分離する。原典でのパターン名は「Ports and Adapters」で、ヘキサゴナルアーキテクチャは図の見た目に由来する別名として併記されている。原典が掲げる意図は「利用者・他プログラム・自動テスト・バッチスクリプトのどれからでも等しく駆動でき、最終的な実行時のデバイスやデータベースから切り離した状態で開発・テストできるようにすること」だ。外から来たイベントは、まずポートで受け止められ、技術固有のアダプターが呼び出しやメッセージへ変換してアプリケーションへ渡す。

図が六角形なのは 6 という数に意味があるからではない。原典は、一次元の層状の図に縛られずポートとアダプターを描き足す余白を確保するための形だと明言している。実際のポート数は 2〜4 個程度が多く、原典の著者も 4 個までしか見たことがないと書いている。「六角形だから 6 層」「6 種類の要素が必要」といった読み方は原典に無い。

構造

ヘキサゴナルアーキテクチャはコア (ビジネスロジック) を中心に、Input Port (外部からコアへの入口) と Output Port (コアから外部への出口) を配置する。外部の技術的詳細 (HTTP、DB、キュー) はポートを介してコアに接続するため、コアは外部に依存しない。テスト時はポートの実装をインメモリに差し替えるだけで済む。

[外部]          [ポート]        [コア]         [ポート]        [外部]
HTTP Request → Input Port → ビジネスロジック → Output Port → DynamoDB
CLI          → Input Port →                → Output Port → SQS
Test         → Input Port →                → Output Port → InMemory
説明
コア (ドメイン)ビジネスロジック注文処理、バリデーション
Input Portコアへの入口OrderService インターフェース
Output Portコアからの出口OrderRepository インターフェース
Input Adapter外部 → コアLambda ハンドラ、CLI
Output Adapterコア → 外部DynamoDB 実装、InMemory 実装

Input / Output という呼び分けは実装側で広まった言い方で、原典では駆動する側を primary (driving) アダプター、駆動される側を secondary (driven) アダプターと呼び、図の左側・右側として説明している。原典を読むときはこの対応で読み替える。左側は自動テストのドライバ、右側はモックやインメモリ実装を差し込む場所にあたる。

TypeScript での実装

TypeScript での実装のコード例を示す。

// Output Port (インターフェース)
interface OrderRepository {
  save(order: Order): Promise<void>;
  findById(id: string): Promise<Order | null>;
}

// コア (ビジネスロジック、外部依存なし)
class OrderService {
  constructor(private repo: OrderRepository) {}
  async create(input: CreateOrderInput): Promise<Order> {
    const order = Order.create(input);
    await this.repo.save(order);
    return order;
  }
}

// Output Adapter: DynamoDB 実装、InMemory 実装など差し替え可能
// Input Adapter: Lambda ハンドラ、CLI など

ヘキサゴナル vs レイヤード vs クリーン

ヘキサゴナル・レイヤード・クリーンの違いを以下にまとめる。

観点ヘキサゴナルレイヤードクリーン
依存の方向外 → 内上 → 下外 → 内
テスト容易性高い高い
複雑さ低い高い

メリット

最大の利点はテスト容易性だ。Output Adapter を InMemory 実装に差し替えるだけで、DB やメッセージキューなしにビジネスロジックをテストできる。また、コアがフレームワーク (Express、Lambda など) に依存しないため、実行環境の変更がコアに波及しない。DB を DynamoDB から Aurora に移行する場合も、Output Adapter を差し替えるだけでコアは無変更で済む。

ヘキサゴナルアーキテクチャについては関連書籍でも詳しく扱われている。

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

関連用語

関連する記事