Архитектура бэкенда
Middleware и DI: тест с множественным выбором
Шесть вопросов, проходящих сквозь весь модуль. Каждый отражает решение, которое вы принимаете на реальном бэкенде — на какой оси лежит проблема, что запрещает контракт, какой lifetime должен быть у объекта — а не определение для пересказа.
Убедитесь, что вы можете разместить проблему на правильной оси (запрос против связывания), рассуждать о порядке middleware и контракте ответа, выбрать scope внедрения и прочитать сбой контейнера — тот синтез, к которому вели шесть уроков.
Обработчик медленный на каждом без исключения эндпоинте, и отдельно — биллинговый класс невозможно юнит-тестировать без обращения к реальному Stripe API. На какой оси лежит каждая проблема?
Express-middleware отправляет res.json(...) при ошибке валидации, а затем ещё и вызывает next(). Под нагрузкой периодически возникает 'Cannot set headers after they are sent'. Какое правило нарушено?
Центральный обработчик ошибок Express, написанный как (err, req, res), никогда не получает ошибки, хотя более ранний код вызывает next(err). Почему и каков фикс?
Периодически пользователь A видит имя аккаунта пользователя B. Аутентификация корректна. Сервис, зарегистрированный как singleton, хранит this.currentUser на запрос. Что произошло и каков самый чистый фикс?
Рефакторинг, сохраняющий поведение, разбивает один repo.save() на два сохранения внутри транзакции. Итоговое состояние идентично, но сорок тестов краснеют. О чём это говорит?
Приложение стартует в dev, но падает в проде с 'Nest can't resolve dependencies of UserService'. AuthService теперь импортирует UserService, который уже импортировал AuthService. Как это прочитать и каков настоящий фикс?
Сквозная нить модуля — одна привычка: назвать ось, затем применить её дисциплину. Ось запроса (middleware) требует одного завершения на middleware и продуманного порядка; error-middleware нужны четыре параметра. Ось связывания (DI) означает, что классы объявляют потребности, а composition root их поставляет — по умолчанию singleton без состояния, повышать scope только вынужденно, а боль тестов читать как сигнал дизайна (мокать границы, которыми вы не владеете, и подделывать то, чем владеете). Контейнер — это тот же composition root, механизированный: он топологически сортирует граф, отвергает циклы и должен падать быстро при старте. Каждый вопрос здесь сводится к этим двум осям и издержкам каждой из них.