Sobes.tech
Senior

Какво знаете за архитектурата на портове и адаптери?

sobes.tech AI

Отговор от 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:

В архитектурата на фронтенда, портовете и адаптерите се прилагат за:

  • Разделяне на бизнес логиката на компонента от източниците на данни: Компонентът взаимодейства с "порт" (интерфейс), който може да бъде реализиран от различни "адаптери" (получаващи данни от 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();