22.06.2026
Rust для мидла: как решить проблему фреймворка
Когда разработчик среднего уровня переходит на Rust, он часто сталкивается с парадоксом: в экосистеме нет «волшебной палочки» вроде Spring Boot или Django. Проблема фреймворка в Rust — это не отсутствие инструментов, а необходимость переосмыслить сам подход к архитектуре. Для мидла это вызов, который превращает привычку «подключить и забыть» в навык «спроектировать и собрать».
Почему традиционный фреймворк не работает в Rust
В языках с сборщиком мусора фреймворк часто берет на себя управление жизненным циклом, инверсию контроля и магию рефлексии. Rust же требует явности. Вы не можете просто поставить аннотацию @Autowired — компилятор заставит вас продумать владение и времена жизни. Проблема фреймворка здесь в том, что готовые решения либо слишком тяжелы (как actix-web с его сложной моделью акторов), либо слишком низкоуровневы (как hyper).
Для мидла ключевой навык — не искать универсальный фреймворк, а собирать свой стек из проверенных крейтов, понимая, как они взаимодействуют через систему типов.
Три столпа решения: композиция, трейты и макросы
1. Композиция вместо наследования
Вместо того чтобы наследовать контроллер от базового класса, в Rust вы строите модули через структуры и трейты. Проблема фреймворка решается через паттерн Builder и внедрение зависимостей через конструктор. Пример: для веб-сервера вы создаете AppState, который хранит пул соединений к БД и конфигурацию, и передаете его в каждый обработчик явно.
2. Трейты как контракты
Вместо того чтобы полагаться на абстрактный класс фреймворка, вы определяете трейты для своих сервисов. Это дает гибкость: вы можете подменить реализацию на мок для тестов, не меняя архитектуру. Проблема фреймворка исчезает, когда вы понимаете, что Rust не требует от вас жертвовать производительностью ради абстракции — трейты компилируются в статический код.
3. Макросы для декларативности
Мидл должен освоить proc_macro и атрибутные макросы. Именно они заменяют магию фреймворков. Например, крейт serde через #[derive(Serialize)] делает за вас всю работу по сериализации. Вы не пишете код фреймворка — вы пишете правила, по которым код генерируется.
Практический пример: собираем минимальный веб-фреймворк
Рассмотрим типичную задачу: нужно обрабатывать HTTP-запросы с авторизацией. Вместо того чтобы тащить тяжелый фреймворк, мы берем:
axum — как легковесный маршрутизатор с поддержкой tower-сервисов.
tower-http — для middleware (логирование, CORS).
sqlx — для работы с БД без ORM.
Архитектура строится так:
Определяем трейт AuthService с методом validate_token.
Реализуем его для конкретного JWT-провайдера.
Через Extension в axum передаем состояние.
В обработчике получаем AuthService из расширения и проверяем токен.
Это не фреймворк в классическом смысле — это архитектура, собранная из кирпичиков. Вы контролируете каждый этап, а компилятор гарантирует, что вы не забудете обработать ошибку.
Типичные ошибки мидла и как их избежать
Первая ошибка — пытаться повторить ООП-паттерны из Java или C#. В Rust это приводит к бесконечным Box и потере производительности. Вторая ошибка — игнорировать времена жизни. Когда вы передаете ссылку на конфиг в обработчик, компилятор может отказать, если время жизни не указано явно. Решение: используйте Arc для разделяемого состояния или клонируйте дешевые данные.
Третья ошибка — бояться писать свои макросы. Мидл должен уметь создавать derive-макросы для рутинных задач. Это не магия, а способ избежать дублирования кода, который в других языках решался бы через рефлексию.
Заключение: фреймворк — это вы
Проблема фреймворка в Rust решается не поиском идеального инструмента, а сменой парадигмы. Вы не потребитель готового решения — вы архитектор, который собирает систему из надежных компонентов. Для мидла это означает переход от «как подключить» к «как спроектировать». Освоив композицию, трейты и макросы, вы перестанете искать фреймворк, потому что сможете создать его под свою задачу за пару часов. И это — истинная сила Rust.