Hexagonal Architecture (Ports and Adapters)

Гексагональная архитектура (Алистер Кокберн) — реинкарнация слоистой/чистой архитектуры с чётко определёнными портами и адаптерами. Бизнес-логика в центре, всё остальное снаружи.

Что это / Зачем

  • Ядро = бизнес-логика (домен + application).
  • Порт — интерфейс, через который ядро общается с внешним миром.
  • Адаптер — конкретная реализация порта (Postgres-адаптер, HTTP-адаптер, Stripe-адаптер).
  • Можно подменять адаптеры без правки ядра: Mongo вместо Postgres, gRPC вместо HTTP.

Driving vs Driven адаптеры

  • Driving (primary) — нас вызывают: HTTP-сервер, GraphQL, CLI, очередь команд.
  • Driven (secondary) — мы вызываем: БД, внешние API, файловое хранилище.
[HTTP] ──┐                                  ┌── [Postgres]
[CLI]  ──┼──> [Port In] [DOMAIN] [Port Out] ──── [Redis]
[Queue]──┘                                  └── [Stripe]
   driving                                  driven

Признаки правильной реализации

  • Доменный код не импортирует Express, Postgres, axios — только интерфейсы.
  • Каждая внешняя зависимость спрятана за портом.
  • Тесты домена работают с in-memory адаптерами, без сети.

Пример

// порт (интерфейс) — в домене
interface UserRepo {
  findById(id: number): Promise<User>;
}

// driven адаптер — в инфраструктуре
class PgUserRepo implements UserRepo {
  async findById(id: number) { return this.db.query(…); }
}

// driving адаптер
class HttpController {
  constructor(private getUser: GetUserUseCase) {}
  async get(req, res) { res.json(await this.getUser.exec(req.params.id)); }
}

Антипаттерн

// доменный сервис импортирует Express и Postgres → не гексагональная
import { Request } from 'express';
import { Pool } from 'pg';
class UserService {
  async create(req: Request) { /* … */ }
}

🎓 Источники

  • 🎓 [Public Interview #7 — Hexagonal Architecture] · 2022-05-13 · YouTube
    • «Гексагональная архитектура — реинкарнация слоёной/чистой архитектуры, в которой чётко определены порты и адаптеры».
    • Характерна Inversion of Control, а не наследование. Mongo vs Postgres — через единый порт.
    • Гексагональная не сложнее чистой — она понятнее: даёт готовые шаблоны для частей приложения.

См. также