Как я перестал бояться и полюбил архитектурную энтропию: рецепт упреждающей инженерии
Осознав масштаб проблемы, я перешёл от реактивной уборки к тому, что называю упреждающей инженерией. Вместо бесконечных ручных чисток в репозитории поселились три скрипта статического аудита. analyze_openapi_entities.py строит матрицу связей сущностей, показывая, какие из них реально используются, а какие — мёртвый груз. find_frontend_orphans.py выискивает компоненты и хуки, не импортируемые нигде, кроме самих себя. analyze_backend_data_flows.py классифицирует каждый эндпоинт по типу доступа к базе и подсвечивает дублирующиеся маршруты. Все отчёты генерируются автоматически и блокируют PR, если артефакты устарели.
Параллельно мы зафиксировали принцип единого источника истины. OpenAPI-спецификация теперь генерируется напрямую из FastAPI-кода, а не пишется вручную. Утилита Orval на её основе создаёт типизированные хуки для фронтенда — так мы избавились от ручного fetch. DBML-диаграмма базы синхронизируется с SQLAlchemy-моделями. Матрицы сущностей и потоков данных не правятся руками — только генерируются. Это исключило расхождение документации и реальности.
Жёсткие конвенции добили оставшиеся лазейки. Скрипт check-no-raw-fetch.sh отклоняет PR, если видит прямой fetch. Для оптимистичных обновлений в UI заведён канонический шаблон с обязательными onMutate, onError и onSettled — никаких падений с 500-й ошибкой. Каждая миграция API завершается командой make generate-api && npx tsc --noEmit. На бэкенде включены mypy strict и Pydantic v2, на фронте вычищены все неявные any (16 файлов, +232/-89 строк) и активирован строгий режим TypeScript. Предметно-ориентированное проектирование и денормализация позволили выделить настоящие агрегаты и радикально сократить число сущностей, убрав дублирующие таблицы и связи.
Результаты не заставили себя ждать. За двое суток (3–5 августа 2026) число таблиц сократилось с 23 до 10 (–57%), 27 миграций объединились в одну, а строки миграционного кода упали на 92%: с 3000 до 227. Из API ушли дублирующие маршруты, ещё 70 устаревших эндпоинтов запланированы к удалению. С фронта исчезли 56 файлов-призраков, все вызовы API теперь идут через сгенерированные хуки. Ноль неявных any, оптимистичные обновления работают надёжно, а аудит стал детерминированным — вместо «кажется, надо почистить» мы получили точные метрики.
Разумеется, сама энтропия никуда не делась: стохастичность LLM не отменить. Однако теперь она видна заранее, а не всплывает внезапно в продакшене. Главный урок, который я вынес: инструменты должны генерировать истину, а люди — задавать правила. Да, на это потребовалось 2274 строки инфраструктурного кода, но теперь каждый PR проверяется автоматически, и разработка с агентами стала предсказуемой. Если вы тоже тонете в агентном хаосе, начните с малого: одна кодогенерируемая схема, один скрипт аудита, один чек-лист. Энтропия отступает ровно в тот момент, когда у неё забирают право быть незаметной.
Осознав масштаб проблемы, я перешёл от реактивной уборки к тому, что называю упреждающей инженерией. Вместо бесконечных ручных чисток в репозитории поселились три скрипта статического аудита. analyze_openapi_entities.py строит матрицу связей сущностей, показывая, какие из них реально используются, а какие — мёртвый груз. find_frontend_orphans.py выискивает компоненты и хуки, не импортируемые нигде, кроме самих себя. analyze_backend_data_flows.py классифицирует каждый эндпоинт по типу доступа к базе и подсвечивает дублирующиеся маршруты. Все отчёты генерируются автоматически и блокируют PR, если артефакты устарели.
Параллельно мы зафиксировали принцип единого источника истины. OpenAPI-спецификация теперь генерируется напрямую из FastAPI-кода, а не пишется вручную. Утилита Orval на её основе создаёт типизированные хуки для фронтенда — так мы избавились от ручного fetch. DBML-диаграмма базы синхронизируется с SQLAlchemy-моделями. Матрицы сущностей и потоков данных не правятся руками — только генерируются. Это исключило расхождение документации и реальности.
Жёсткие конвенции добили оставшиеся лазейки. Скрипт check-no-raw-fetch.sh отклоняет PR, если видит прямой fetch. Для оптимистичных обновлений в UI заведён канонический шаблон с обязательными onMutate, onError и onSettled — никаких падений с 500-й ошибкой. Каждая миграция API завершается командой make generate-api && npx tsc --noEmit. На бэкенде включены mypy strict и Pydantic v2, на фронте вычищены все неявные any (16 файлов, +232/-89 строк) и активирован строгий режим TypeScript. Предметно-ориентированное проектирование и денормализация позволили выделить настоящие агрегаты и радикально сократить число сущностей, убрав дублирующие таблицы и связи.
Результаты не заставили себя ждать. За двое суток (3–5 августа 2026) число таблиц сократилось с 23 до 10 (–57%), 27 миграций объединились в одну, а строки миграционного кода упали на 92%: с 3000 до 227. Из API ушли дублирующие маршруты, ещё 70 устаревших эндпоинтов запланированы к удалению. С фронта исчезли 56 файлов-призраков, все вызовы API теперь идут через сгенерированные хуки. Ноль неявных any, оптимистичные обновления работают надёжно, а аудит стал детерминированным — вместо «кажется, надо почистить» мы получили точные метрики.
Разумеется, сама энтропия никуда не делась: стохастичность LLM не отменить. Однако теперь она видна заранее, а не всплывает внезапно в продакшене. Главный урок, который я вынес: инструменты должны генерировать истину, а люди — задавать правила. Да, на это потребовалось 2274 строки инфраструктурного кода, но теперь каждый PR проверяется автоматически, и разработка с агентами стала предсказуемой. Если вы тоже тонете в агентном хаосе, начните с малого: одна кодогенерируемая схема, один скрипт аудита, один чек-лист. Энтропия отступает ровно в тот момент, когда у неё забирают право быть незаметной.