GoF以外のプログラミング・デザインパターン #06 Hexagonal Architecture

2025/11/27

プログラミング 学習

t f B! P L
eyecatch Hexagonal Architecture(ヘキサゴナルアーキテクチャ)は、別名「Ports and Adapters(ポートとアダプター)アーキテクチャ」とも言われます。 アプリケーションの中核(ドメイン)を外部要素から独立させる設計思想です。 2005年にAlistair Cockburnによって提唱されました。 外部との接続を“六角形(Hexagon)”の辺=ポートとして抽象化します。

基本構造イメージ

UI / CLI / API

外部入出力(Adapter) ↓ [Inbound Port] │

Application Core

ドメイン・ユースケース ↓ [Outbound Port] │

DB / File / API

外部システム(Adapter)

構成要素の役割

Core(中心部:ドメイン+ユースケース)

・アプリケーションの本質的なビジネスロジック。 ・外部技術(DB、Web、UIなど)に一切依存しない。 ・例:TodoService, OrderProcessor, UserDomain など。

Ports(ポート)

・Coreが外部とやり取りする抽象的なインターフェース。 ・「どんな操作ができるか」を定義する。 ・次の2種類ある: 1. Inbound Port:外部からCoreへ(例:API → Service呼び出し) 2. Outbound Port:Coreから外部へ(例:DB保存、外部API呼び出し)

Adapters(アダプター)

・Portsの具体的な実装を担う層。 ・外部の仕組み(Web・DB・外部サービスなど)を接続する役割。 ・例: 1. Inbound Adapter → REST API, CLI, WebSocketなど 2. Outbound Adapter → DBアクセス, メール送信, 外部APIクライアントなど

データフロー

(例:ユーザー登録)
[REST API] ↓ [Inbound Adapter] ↓ [Inbound Port] ↓ [Application Core] ↓ [Outbound Port] ↓ [DB Adapter] ↓ [Database]

構造イメージ

📦 hex-todo/ ┣ 📂 core/ ┃ * ドメイン+ユースケース ┃ ┣ todoService.js ┃ ┗ ports/ ┃ ┣ todoRepositoryPort.js ┃ ┃ * Outbound Port ┃ ┗ todoInputPort.js ┃ * Inbound Port ┣ 📂 adapters/ ┃ ┣ inbound/ ┃ ┃ ┗ restTodoController.js ┃ ┗ outbound/ ┃ ┗ memoryTodoRepository.js ┗ index.js
core(ビジネスロジック)は「Express」や「MongoDB」などに依存せずに動作するのがポイント。

メリット

・ビジネスロジックの独立性が高い(DBやUI変更の影響を受けない)。 ・テスト容易性が高い(モックPortでユニットテスト可能)。 ・拡張性が高い(異なるUIやDBを簡単に差し替えできる)。 ・Clean Architectureの基盤思想になっている。

デメリット

・小規模アプリでは構成がやや複雑(設計コスト増)。 ・「Port」と「Adapter」の関係を明確に分離する設計力が必要。 ・クラスやファイルが増えやすい。

サンプルコード

ファイル階層

src/ ├ domain/ │ ├ model/ │ │ └ User.js │ └ service/ │ └ UserService.js ├ application/ │ └ UserUseCase.js ├ infrastructure/ │ ├ persistence/ │ │ └ UserRepositoryMemory.js │ └ controller/ │ └ UserController.js └ index.js

domain/model/User.js

export class User { constructor(id, name, email) { this.id = id this.name = name this.email = email } }

domain/service/UserService.js

export class UserService { constructor(userRepository) { this.userRepository = userRepository } createUser(name, email) { const id = Date.now() const user = { id, name, email } this.userRepository.save(user) return user } getAllUsers() { return this.userRepository.findAll() } }

application/UserUseCase.js

export class UserUseCase { constructor(userService) { this.userService = userService } registerUser(name, email) { return this.userService.createUser(name, email) } listUsers() { return this.userService.getAllUsers() } }

infrastructure/persistence/UserRepositoryMemory.js

export class UserRepositoryMemory { constructor() { this.users = [] } save(user) { this.users.push(user) } findAll() { return this.users } }

infrastructure/controller/UserController.js

export class UserController { constructor(userUseCase) { this.userUseCase = userUseCase } create(req, res) { const { name, email } = req const user = this.userUseCase.registerUser(name, email) res(user) } list(req, res) { const users = this.userUseCase.listUsers() res(users) } }

index.js(エントリーポイント)

import { UserRepositoryMemory } from './infrastructure/persistence/UserRepositoryMemory.js' import { UserService } from './domain/service/UserService.js' import { UserUseCase } from './application/UserUseCase.js' import { UserController } from './infrastructure/controller/UserController.js' // 依存注入 const repo = new UserRepositoryMemory() const service = new UserService(repo) const useCase = new UserUseCase(service) const controller = new UserController(useCase) // 疑似HTTPリクエスト controller.create({ name: 'Taro', email: 'taro@example.com' }, console.log) controller.create({ name: 'Hanako', email: 'hanako@example.com' }, console.log) controller.list({}, console.log)

ポイント解説

ドメイン層(domain/) → ビジネスロジックを保持。外部技術とは無関係。 アプリケーション層(application/) → ユースケース単位の操作を提供。 インフラ層(infrastructure/) → データ永続化やI/O操作を担当。 ポートとアダプタ → UserServiceがポート、UserRepositoryMemoryがアダプタ。

Layered Architectureとの違い

比較項目 Layered Architecture Hexagonal Architecture
構造上下の層構造 中心から外へ広がる六角構造
依存方向 一方向(上→下) ドメインを中心に内向き依存
柔軟性 中程度 高い(外部切替が容易)
主眼 責務の階層分離 技術依存の分離と独立性
代表例 MVC, 3層構造 Clean Architecture, Onion Architecture

あとがき

Layered Architectureをより発展させたデザインパターンです。 テスト効率が良いですが、ファイルが増えがちになるのは、なんとも悩ましい感じですね。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ