Структура проекта с Iron и Express

При совместном использовании Iron и Express важно сразу определить границы ответственности между двумя слоями. Express чаще используется как гибкий HTTP-сервер с богатой экосистемой middleware, тогда как Iron обычно выступает как более структурированный каркас для маршрутизации и организации бизнес-логики.

Ключевая идея архитектуры — разделение приложения на слои:

  • слой HTTP-инфраструктуры (Express)
  • слой маршрутизации и контроллеров (Iron)
  • слой бизнес-логики (services)
  • слой доступа к данным (repositories / models)

Такое разделение позволяет избежать смешивания логики обработки запросов и доменной логики, что критично для масштабируемых приложений.


Общая структура каталогов

Типичный проект с использованием Iron и Express строится вокруг предсказуемой и расширяемой структуры:

project-root/
│
├── src/
│   ├── app/                 # точка интеграции Express и Iron
│   ├── config/             # конфигурации окружения
│   ├── routes/             # маршруты Iron
│   ├── controllers/        # контроллеры (HTTP слой)
│   ├── services/           # бизнес-логика
│   ├── repositories/       # работа с данными
│   ├── middlewares/       # middleware Express и Iron
│   ├── utils/              # вспомогательные функции
│   ├── models/             # модели данных
│   └── errors/             # обработка ошибок
│
├── public/                # статические файлы (Express)
├── tests/                 # тесты
├── package.json
└── server.js              # запуск приложения

Точка входа приложения

В проектах, где Express используется как базовый HTTP-сервер, а Iron как слой маршрутизации, точка входа обычно выглядит как связующий модуль.

Основная задача этого слоя — инициализация Express и подключение Iron как маршрутизатора.

Примерная структура логики:

  • создание экземпляра Express
  • подключение middleware
  • подключение Iron router
  • запуск сервера

Ключевым моментом является то, что Express не должен знать о бизнес-логике — он только передаёт управление Iron.


Интеграция Iron в Express

Интеграция строится вокруг передачи управления маршрутизацией.

Express выступает как контейнер HTTP-уровня, а Iron — как слой обработки маршрутов:

  • Express принимает входящий запрос
  • передаёт его в Iron router
  • Iron определяет маршрут и вызывает соответствующий контроллер
  • результат возвращается обратно в Express response

Такая схема позволяет:

  • централизовать маршруты в Iron
  • оставить Express только как транспортный слой
  • упростить масштабирование

Организация маршрутов Iron

Маршруты в Iron структурируются по функциональному признаку, а не по техническому.

Пример логической группировки:

  • auth маршруты
  • user маршруты
  • product маршруты
  • admin маршруты

Каждая группа маршрутов находится в отдельном модуле:

routes/
├── auth.routes.js
├── user.routes.js
├── product.routes.js

Внутри каждого файла описываются маршруты и привязка к контроллерам:

  • GET /users
  • POST /users
  • GET /users/:id

Важно, что Iron обычно позволяет более декларативную организацию маршрутов, что упрощает поддержку.


Контроллеры как слой адаптации

Контроллеры не должны содержать бизнес-логику. Их задача:

  • принять запрос
  • извлечь параметры
  • вызвать сервисный слой
  • сформировать HTTP-ответ

Типовая структура контроллера:

  • validation входных данных
  • вызов service
  • обработка результата
  • обработка ошибок

Контроллер становится адаптером между HTTP и доменной логикой.


Слой сервисов

Сервисы представляют собой ядро бизнес-логики приложения.

Их особенности:

  • независимость от Express и Iron
  • отсутствие HTTP-кода
  • переиспользуемость

Примеры задач сервиса:

  • создание пользователя
  • обработка заказов
  • вычисление бизнес-правил

Сервисы позволяют тестировать бизнес-логику отдельно от инфраструктуры.


Репозитории и доступ к данным

Репозитории отделяют работу с базой данных от бизнес-логики.

Функции слоя:

  • выполнение SQL-запросов или ORM-операций
  • преобразование данных
  • инкапсуляция источника данных

Сервисы никогда не должны напрямую обращаться к базе данных — только через repository слой.


Middleware слой Express и Iron

Middleware в таком проекте делится на два типа:

Express middleware

  • логирование запросов
  • CORS
  • парсинг тела запроса
  • обработка статических файлов

Iron middleware

  • авторизация на уровне маршрутов
  • проверка прав доступа
  • предварительная обработка параметров маршрута

Важно избегать дублирования логики между слоями.


Обработка ошибок

Централизованная обработка ошибок является обязательной частью архитектуры.

Стандартный подход:

  • сервисы выбрасывают ошибки доменного уровня
  • контроллеры не обрабатывают детали ошибок
  • Express middleware перехватывает ошибки
  • формируется единый формат ответа

Структура ошибок обычно включает:

  • код ошибки
  • сообщение
  • дополнительный контекст

Конфигурация проекта

Конфигурация должна быть отделена от логики приложения.

Обычно выделяются:

  • переменные окружения
  • настройки базы данных
  • параметры сервера
  • настройки безопасности

Файлы конфигурации не должны содержать бизнес-логики или вызовов Express/Iron.


Связь между слоями

В правильно организованной структуре зависимости направлены строго вниз:

Express → Iron → Controllers → Services → Repositories → DB

Нарушение этого направления приводит к:

  • циклическим зависимостям
  • трудностям тестирования
  • снижению масштабируемости

Пример логического потока запроса

При запросе GET /users/10:

  • Express принимает HTTP запрос
  • передаёт его в Iron router
  • Iron находит маршрут /users/:id
  • вызывается контроллер
  • контроллер вызывает UserService
  • сервис обращается к UserRepository
  • репозиторий получает данные из базы
  • результат возвращается обратно по цепочке
  • Express отправляет JSON-ответ клиенту

Разделение публичной и внутренней логики

Проект часто делится на две зоны:

  • публичная API часть (Express + Iron маршруты)
  • внутренняя бизнес-логика (services, repositories)

Такое разделение позволяет:

  • переиспользовать бизнес-логику вне HTTP (например, cron-задачи)
  • тестировать систему без сервера
  • легко масштабировать архитектуру

Масштабирование структуры проекта

По мере роста проекта структура может расширяться:

  • добавление domain-слоя (DDD подход)
  • введение event-driven архитектуры
  • выделение отдельных модулей (modules/users, modules/orders)
  • подключение очередей задач

Важно сохранять правило: каждый слой не должен знать о реализации слоя ниже, только о его интерфейсе.