awesome-everything EN
↑ Обратно к восхождению

Архитектура бэкенда

Middleware и DI: соберите тестируемый сервис

Суть Практический проект — собрать небольшой сервис с корректным pipeline middleware и внедрённым графом объектов в одном composition root, затем доказать шов, scope и порядок тестами и нагрузочным прогоном.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 240 min

Читать о двух осях — не то же самое, что связать их. Соберите небольшой сервис, где pipeline middleware намеренно упорядочен, граф объектов собран в одном composition root, каждый выбор scope обоснован, а тестовый шов реален — затем докажите каждое свойство тестом или измерением.

Цель

Превратите ментальную модель модуля в работающий сервис: корректный упорядоченный pipeline middleware; composition root без скрытого new в бизнес-логике; намеренные выборы singleton/request/transient; шов, который вы проверяете и через fake, и через mock границы; и доказательство, что порядок и scope ведут себя как задумано под нагрузкой.

Проект
0 из 7
Цель

Соберите небольшой HTTP-сервис (Express, Koa, Fastify или NestJS) с одним реальным доменным сценарием (например, оформить заказ или создать пользователя), у которого и pipeline middleware, и граф зависимостей корректны по дизайну — затем докажите корректность тестами и коротким нагрузочным прогоном, а не утверждением.

Требования
Критерии приёмки
  • Запрос проходит из конца в конец через упорядоченный pipeline; неаутентифицированный или ограниченный по частоте запрос отклоняется до дорогого шага парсинга тела, что показано тестом или логом/трейсом.
  • Ни один класс бизнес-логики не конструирует своих коллабораторов — весь граф собран в composition root, что проверяется grep по доменному коду на new для внедряемых типов.
  • Тест на основе состояния переживает рефакторинг, сохраняющий поведение (например, разбиение одного save на два), тогда как mock границы всё ещё проверяет внешний вызов — показывая, что вы замокали границу и подделали то, чем владеете.
  • Scope каждого провайдера обоснован, и короткая заметка объясняет, почему ни один singleton не держит состояние на запрос и почему любой request-scoped провайдер был неизбежен.
Senior-стретч
  • Внесите намеренную циклическую зависимость между двумя сервисами, понаблюдайте ошибку резолвинга контейнера, затем уберите цикл, вынеся общий третий класс — и опишите, почему forwardRef лишь спрятал бы её.
  • Добавьте request-scoped провайдер глубоко в граф, прогоните нагрузку до и после и измерьте издержки аллокаций/латентности от scope bubbling против передачи значения аргументом.
  • Переключите режим старта eager/lazy (или сымитируйте отсутствующую зависимость) и покажите, что eager-инстанцирование превращает неверную конфигурацию в громкий сбой при старте вместо тихого сбоя на первом запросе.
  • Портируйте тот же сервис на второй фреймворк (например, Express на Fastify) и сравните, как для одного и того же pipeline различаются модель middleware и инкапсуляция.
Итог

Это цикл, который вы запускаете на каждом реальном бэкенде: упорядочьте pipeline так, чтобы дешёвые отказы шли первыми, а один терминальный обработчик ловил остальное; соберите граф в одном composition root, чтобы ни один класс логики не конструировал коллабораторов; выбирайте каждый scope намеренно и держите singleton без состояния; и используйте шов, чтобы подделывать то, чем владеете, и мокать границы, которыми не владеете. Сделав это раз на небольшом сервисе, вы делаете две оси — запрос и связывание — автоматическими при чтении продакшен-кода.

Продолжить восхождение ↑Блокирующий vs неблокирующий I/O: два способа ждать
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.