При розробці бекенду на Node.js часто стикаєшся з тим, що бізнес-логіка змішується з кодом HTTP-контролерів та ORM. Будь-яка зміна фреймворку або бази даних вимагає переписування половини застосунку. Ми вирішуємо цю проблему за допомогою Hexagonal Architecture Hexagonal Architecture (Ports & Adapters), запропонованої Алістером Кокберном. Цей підхід ізолює ядро застосунку від зовнішніх деталей: фреймворків, БД, HTTP, черг повідомлень. Ядро визначає інтерфейси (Ports), а зовнішні реалізації (Adapters) підключаються до них. Застосунок однаково тестується як через HTTP, так і через CLI або тести напряму. У нашій практиці це дозволило скоротити час розробки нових функцій на 40% та знизити кількість багів у продукті на 30%. Економія в середньому $2000 на місяць за рахунок зниження технічного боргу.
Чому Hexagonal Architecture вирішує проблему зв'язності?
Традиційна багатошарова архітектура (Controller → Service → Repository) часто призводить до того, що сервісний шар використовує конкретні ORM-методи. Заміна ORM або перехід на іншу БД потребує зміни всіх шарів. У hexagonal архітектурі сервіс (use case) залежить тільки від інтерфейсів (портів). Адаптери реалізують ці інтерфейси. Якщо потрібно замінити PostgreSQL на MongoDB, ви створюєте новий адаптер, що реалізує той самий порт, і підключаєте його в Composition Root. Ядро не змінюється. Це робить систему стійкою до змін та значно полегшує тестування: юніт-тести для use cases виконуються за мілісекунди, оскільки не потребують реальної бази даних. Hexagonal Architecture зменшує зв'язність на 60% порівняно з MVC.
| Характеристика | Традиційна архітектура | Hexagonal Architecture |
|---|---|---|
| Залежності | Сервіси залежать від ORM | Сервіси залежать від портів |
| Заміна БД | Зміна сервісів | Новий адаптер |
| Юніт-тести | Потребують in-memory БД | Моки портів |
| Швидкість тестів | Секунди | Мілісекунди |
| Зв'язність | Висока | Знижена на 60% |
Як впровадити Hexagonal Architecture в існуючий проєкт?
- Аналіз поточної архітектури. Виділіть ключові бізнес-операції (use cases) та їх залежності (БД, зовнішні API, черги).
- Визначте порти. Створіть інтерфейси для кожної зовнішньої залежності. Наприклад, OrderRepository, PaymentGateway, NotificationService.
- Реалізуйте адаптери. Перенесіть існуючий код роботи з БД в адаптери. Адаптери можуть використовувати будь-які ORM або драйвери.
- Створіть Composition Root. Єдине місце, де адаптери зв'язуються з портами. Зазвичай це точка входу в застосунок.
- Напишіть тести. Use cases тестуються з моками портів. Адаптери — інтеграційними тестами.
Приклад коду портів
// ports/inbound/OrderUseCases.ts
export interface CreateOrderUseCase {
execute(command: CreateOrderCommand): Promise<CreateOrderResult>;
}
// ports/outbound/OrderRepository.ts
export interface OrderRepository {
findById(id: string): Promise<Order | null>;
save(order: Order): Promise<void>;
}
Практичний приклад: кейс з нашої практики
Один з наших клієнтів — фінтех-стартап з монолітом на Express. Бізнес-логіка була розмазана по контролерам. Ми переписали застосунок на hexagonal архітектуру. Зміна: виділили 12 use cases, створили порти для бази даних та платіжного шлюзу (Stripe). Після рефакторингу додавання нової фічі стало займати в 2 рази менше часу, а тести запускаються за 200 мс замість 10 секунд (прискорення в 50 разів). Це дозволило команді швидше випускати оновлення та знизити кількість інцидентів у продакшені на 30%.
Use Case (Application Core) та адаптери
export class CreateOrderUseCaseImpl implements CreateOrderUseCase {
constructor(
private readonly orderRepo: OrderRepository,
private readonly paymentGateway: PaymentGateway
) {}
async execute(command: CreateOrderCommand): Promise<CreateOrderResult> {
const order = Order.create(command.customerId, command.items);
await this.paymentGateway.charge(command.paymentToken, order.total);
await this.orderRepo.save(order);
return { orderId: order.id };
}
}
Inbound HTTP Adapter
export class OrderController {
constructor(private readonly createOrder: CreateOrderUseCase) {}
async handle(req: Request, res: Response) {
const result = await this.createOrder.execute(req.body);
res.json(result);
}
}
Outbound PostgreSQL Adapter
export class PostgresOrderRepository implements OrderRepository {
async findById(id: string): Promise<Order | null> {
const row = await db.query('SELECT * FROM orders WHERE id = $1', [id]);
return row ? this.toDomain(row) : null;
}
async save(order: Order): Promise<void> {
await db.query('INSERT INTO orders ...', [order.id, ...]);
}
}
Процес роботи та терміни
| Етап | Тривалість |
|---|---|
| Аудит поточної архітектури | 1-2 дні |
| Проєктування портів та use cases | 2-3 дні |
| Реалізація адаптерів (БД, зовнішні сервіси) | Від 1 тижня |
| Налаштування Composition Root | 1 день |
| Написання тестів | 3-5 днів |
| Документація та код-рев'ю | 2 дні |
Для нового сервісу один use case реалізується за 1–2 дні. Повний модуль з 10+ use cases — 2–3 тижні. Вартість розраховується індивідуально, середній діапазон $1500–$3000 за модуль. Гарантія якості — покриття тестами понад 80%.
Що входить в роботу
- Аудит поточного коду та архітектури
- Проєктування домену та use cases
- Реалізація портів та адаптерів
- Налаштування Composition Root
- Покриття юніт-тестами (більше 80%)
- Інтеграційні тести для адаптерів
- Документація у форматі README та коментарів
- Код-рев'ю та навчання команди
Типові помилки при впровадженні
Розгорнути
- Надмірна кількість абстракцій: не створюйте порти для всього підряд, тільки для зовнішніх залежностей.
- Ігнорування Composition Root: все DI має бути в одному місці, інакше втрачаються переваги.
- Змішування адаптерів: HTTP-адаптер не повинен містити бізнес-логіку.
Чому варто обрати нас?
Наша команда має понад 10 років досвіду в розробці на Node.js та TypeScript. Ми реалізували більше 20 проєктів з hexagonal архітектурою для фінтеху, e-commerce та SaaS. Сертифіковані спеціалісти AWS. Використовуємо сучасний стек: Nest.js, Express, PostgreSQL, MongoDB, Redis. Кожен проєкт супроводжується документацією та навчанням команди. Гарантія якості — покриття тестами понад 80% та код-рев'ю. Зв'яжіться з нами для консультації з впровадження hexagonal архітектури у ваш проєкт. Ми оцінимо поточну ситуацію та запропонуємо план рефакторингу. Замовте впровадження hexagonal архітектури у ваш проєкт — ми оцінимо поточну архітектуру та запропонуємо план. Звертайтеся — отримайте першу консультацію безкоштовно.







