Назад к вопросам
Senior
780
questionbank

Что вы знаете об архитектуре портов и адаптеров?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Архитектура портов и адаптеров, также известная как гексагональная архитектура (Hexagonal Architecture), отделяет логику предметной области приложения (Core) от внешних зависимостей (интерфейсов пользователя, баз данных, внешних сервисов).

Основные концепции:

  • Порты: Определяют интерфейсы, через которые Core взаимодействует с внешним миром. Порты бывают двух типов:
    • Входящие (Driving Ports): Используются внешними сущностями для вызова функциональности Core (например, API-интерфейс).
    • Исходящие (Driven Ports): Используются Core для вызова функциональности внешних сущностей (например, интерфейс репозитория для доступа к данным).
  • Адаптеры: Реализуют порты, подключая Core к конкретным внешним технологиям или фреймворкам.
    • Входящие (Driving Adapters): Реализуют входящие порты и преобразуют входящие запросы из внешней среды в вызовы Core (например, REST-контроллер).
    • Исходящие (Driven Adapters): Реализуют исходящие порты и преобразуют вызовы из Core для взаимодействия с внешней средой (например, реализация репозитория для работы с конкретной базой данных).
  • Core (Предметная область): Содержит бизнес-логику приложения. Он полностью изолирован от внешних деталей и взаимодействует с ними только через порты.

Преимущества:

  • Тестируемость: Изоляция Core облегчает юнит-тестирование бизнес-логики без необходимости мокировать сложные внешние зависимости.
  • Гибкость: Позволяет легко заменять или добавлять новые внешние технологии (базы данных, фреймворки) без изменения Core. Достаточно написать новый адаптер для существующего порта.
  • Чистый код: Способствует созданию более чистого и поддерживаемого кода, фокусируя Core только на бизнес-правилах.
  • Разделение ответственности: Четко разделяет зоны ответственности.

Связь с Frontend:

На Frontend архитектура портов и адаптеров применима для:

  • Отделения бизнес-логики компонента от источников данных: Компонент взаимодействует с "портом" (интерфейсом), который может быть реализован разными "адаптерами" (получающими данные из API, Local Storage, тестовых моков и т.д.).
  • Обработки внешних событий: Входящие порты могут представлять обработчики событий UI, а адаптеры преобразуют эти события в вызовы внутренней логики.
  • Инкапсуляции взаимодействия с внешними библиотеками: Адаптеры могут оборачивать обращения к сторонним библиотекам (например, библиотеке для работы с картами), предоставляя Core простой и стабильный интерфейс.

Пример на JavaScript (схема):

// Пример исходящего порта (интерфейс для получения данных)
class DataGateway {
  getData() {
    throw new Error("Метод getData должен быть реализован");
  }
}

// Пример исходящего адаптера (реализация порта для API)
class ApiDataGateway extends DataGateway {
  async getData() {
    const response = await fetch('/api/data');
    return response.json();
  }
}

// Пример входящего порта (интерфейс для бизнес-логики)
class BusinessLogicPort {
  constructor(dataGateway) {
    this.dataGateway = dataGateway;
  }

  async processData() {
    throw new Error("Метод processData должен быть реализован");
  }
}

// Пример Core (бизнес-логика)
class MyBusinessLogic extends BusinessLogicPort {
  async processData() {
    const data = await this.dataGateway.getData();
    // Логика обработки данных
    console.log("Данные обработаны:", data);
    return data;
  }
}

// Пример входящего адаптера (использование логики в UI)
async function initApp() {
  const apiGateway = new ApiDataGateway(); // Конкретный адаптер
  const businessLogic = new MyBusinessLogic(apiGateway); // Core использует порт
  await businessLogic.processData(); // Входящий адаптер вызывает Core
}

initApp();