8 признаков того, что архитектура вашего проекта уже сломана

Разработка ПО
Блог
8 признаков того, что архитектура вашего проекта уже сломана
Поделиться:


                

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

Ниже — 8 конкретных признаков, по которым можно диагностировать состояние системы. Не абстрактные «плохой код» и «отсутствие документации», а поведенческие симптомы, которые можно наблюдать прямо сейчас.

Почему архитектурные проблемы замечают поздно

Баг виден сразу: что-то упало, пользователь пожаловался, мониторинг сработал. Архитектурный долг не виден — он накапливается в решениях, которые «работают, но не очень». Команда привыкает к медленным деплоям, к тому что «лучше не трогать модуль X», к онбордингу, который занимает полтора месяца.

К моменту, когда проблема становится очевидной, она уже стоит дорого. По данным McKinsey (2022), технический долг составляет в среднем 20–40% от стоимости IT-активов компаний, а его обслуживание съедает до 10–15% бюджета разработки. Архитектурные проблемы — самая дорогая часть этого долга.

Признак 1 — Любое изменение ломает что-то еще

Это самый надежный индикатор. Поменяли название поля в таблице users — сломалось три сервиса, которые, казалось бы, вообще не работают с пользователями. Добавили параметр в метод — упали тесты в модуле, который писали год назад.

За этим стоит высокая связность (tight coupling): компоненты системы знают слишком много друг о друге. В хорошей архитектуре модули взаимодействуют через четкие интерфейсы и не зависят от внутренней реализации соседа. Когда этого нет — изменение в одном месте расходится волнами по всей кодовой базе.

Практический тест: попросите разработчика изменить одну небольшую вещь и посчитайте, сколько файлов он откроет. Больше 5–7 при локальном изменении — повод задуматься.

Признак 2 — Нет возможности покрыть код тестами

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

Хороший признак тестируемости: можно взять любой класс или функцию, передать ей входные данные и проверить результат — без побочных эффектов и внешних зависимостей. Если это невозможно, логика размазана там, где ее не должно быть.

Низкое тестовое покрытие само по себе еще не диагноз — иногда команда просто не писала тесты. Диагноз — когда написать тест физически сложно. Это разные вещи.

Признак 3 — Онбординг нового разработчика занимает больше месяца

Хорошая архитектура данных проекта читается. Если новый человек может за день-два понять, где живет бизнес-логика, как данные движутся через систему и почему принято именно такое решение — архитектура работает. Если через три недели он все еще задает вопросы «а почему здесь так?» — нет.

Долгий онбординг — симптом нескольких вещей сразу: документация отстала от реальности (или ее нет), логика размазана по неожиданным местам, неймингоконвенций нет или они не соблюдаются. Все это — признаки деградации архитектурного качества, а не плохой памяти нового разработчика.

Как быстро проверить — задайте новичку вопрос

Попросите человека, который работает в проекте меньше двух недель, найти, где обрабатывается конкретный бизнес-сценарий — например, «где происходит расчет скидки». Если он находит это за 15 минут — архитектура читается. Если нет — система не говорит сама о себе.

Признак 4 — Деплой занимает часы и требует ритуалов

Когда процесс выкатки — это ручная последовательность из 12–20 шагов, которую знает один-два человека и которая периодически «не работает по непонятным причинам» — архитектура не поддерживает автоматизацию. CI/CD не настраивается поверх любого кода. Для него нужна предсказуемая, детерминированная система.

Симптомы этого признака:

  • деплой нельзя запустить в любое время — есть «окна» и «запрещенные дни»
  • после каждого деплоя проверяется вручную список из N пунктов
  • откат к предыдущей версии занимает больше часа
  • деплой одного сервиса требует координации с тремя командами

Если хотя бы два пункта совпали — это уже сигнал.

Признак 5 — Архитектура данных проекта не отражает бизнес-логику

Таблица называется user_data, но хранит заказы. Статус заказа вычисляется из комбинации трех полей в двух разных таблицах. Чтобы понять, активен ли пользователь, нужно написать запрос на 40 строк с четырьмя JOIN-ами.

Это классический признак расхождения между доменной моделью и моделью данных. Хорошая архитектура данных проекта — когда схема БД примерно соответствует языку бизнеса: сущности называются так же, как их называют аналитики и продакты, а правила — одно место, а не пять.

Когда этого нет, каждый новый разработчик строит в голове свою ментальную карту системы. Карты у всех разные. Это источник багов, которые невозможно предсказать.

Признак 6 — Производительность правится хаками, а не архитектурой

Запросы медленные — добавили кеш везде. Кеши устаревают непредсказуемо — добавили инвалидацию, которая работает «почти всегда». База перегружена — денормализовали несколько таблиц без общей схемы. Через год никто не понимает, почему данные в трех местах разные.

Патчи поверх патчей — это не оптимизация, это симптом. В хорошей архитектуре перформанс-решения принимаются системно: где кешировать и почему, как инвалидировать, какие запросы должны быть быстрыми по природе системы. Когда этого плана нет — каждый «фикс» создает два новых ограничения.

Признак 7 — Команда боится трогать отдельные части кода

«Не трогай payment.service.js — там все упадет». «Лучше не менять эту функцию — никто не знает, кто ее вызывает». Если в проекте есть такие места — а они есть почти в каждом проекте старше двух лет — это не проблема конкретного файла. Это симптом архитектурного страха.

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

Косвенный показатель: если спросить команду «какой модуль вы меньше всего хотите трогать?» — и все назовут одно и то же место — это оно.

Признак 8 — Новые фичи реализуются в 3–5 раз медленнее, чем год назад

Это самый измеримый признак из всех. Velocity команды падает — а команда не уменьшилась, задачи не стали сложнее. Просто каждая новая фича требует все больше времени на «разобраться как это работает», «не сломать существующее» и «протестировать вручную, потому что автотестов нет».

Если вы ведете метрики (story points, cycle time, lead time) — посмотрите на тренд за 12 месяцев. Падение производительности без роста команды или резкого усложнения задач — прямой индикатор архитектурного торможения.

Отсутствие метрик само по себе тоже симптом, но другой истории.

Таблица: симптом — последствие — степень риска

Признак

Последствие

Риск

Любое изменение что-то ломает

Высокая стоимость любой правки; рост страха изменений

Высокий

Невозможно написать тест

Баги в продакшне не выявляются до релиза

Высокий

Онбординг > 1 месяца

Медленный найм, высокая зависимость от ключевых людей

Средний

Деплой занимает часы

Медленный цикл обратной связи; риск долгих простоев

Средний–высокий

Данные не отражают бизнес

Баги в бизнес-логике; сложность поддержки отчетности

Высокий

Перформанс правится хаками

Непредсказуемое поведение под нагрузкой; рост tech debt

Средний–высокий

Страшные модули в коде

Ключевые части системы не развиваются; риск критических сбоев

Высокий

Velocity упала в 3–5 раз

Прямые потери выручки; выгорание команды

Критический

Что делать, если нашли 3 и более признака

Первый инстинкт — переписать все с нуля. Почти всегда это ошибка. Переписывание убивает функциональность, которая «просто работала» и о которой никто не помнит, занимает вдвое больше запланированного времени и дает ту же архитектуру, только свежую — если команда не изменила подход.

Рабочий путь — поэтапный архитектурный рефакторинг:

  1. Аудит. Зафиксируйте все 8 признаков применительно к вашей системе. Какие есть, какие нет, где они проявляются сильнее всего. Это карта проблемы.
  2. Изоляция критических зон. Определите модули с наибольшим риском (страшные места + высокая связность). Их трогать последними — сначала стабилизировать периметр.
  3. Покрытие тестами перед изменениями. Прежде чем рефакторить модуль — покрыть его интеграционными тестами на текущее поведение. Это страховка, которая позволяет двигаться быстрее.
  4. Strangler Fig Pattern. Новая функциональность пишется по новым принципам, старая остается работать. Постепенно старый код «душится» новым. Это стандартный подход для больших легаси-систем.
  5. Метрики до и после. Без измерений непонятно, движетесь ли вы в правильную сторону. Cycle time, покрытие тестами, время деплоя, время онбординга — хотя бы четыре метрики.

FAQ — частые вопросы об архитектурных проблемах

Сколько признаков из восьми — это уже критично?

Три и больше — повод провести архитектурный аудит. Пять и больше — риск, который влияет на бизнес прямо сейчас, даже если это еще не заметно в выручке. Все восемь встречаются в системах, которые существуют 5–10 лет без рефакторинга.

Можно ли предотвратить архитектурный долг?

Полностью — нет. Требования меняются, технологии устаревают, команды ротируются. Но темп накопления долга можно контролировать: регулярные ревью архитектуры, ADR (Architecture Decision Records), выделенное время на рефакторинг в каждом спринте.

Насколько переписать с нуля хуже рефакторинга?

Джоэл Спольски назвал полное переписывание «худшей стратегической ошибкой в разработке ПО» еще в 2000 году — и это не утратило актуальности. Переписывание занимает 2–3 года вместо запланированного одного, замораживает разработку новых фич и в большинстве случаев воспроизводит те же архитектурные ошибки, только свежим кодом.

Как убедить бизнес выделить время на архитектурный рефакторинг?

Переводите в деньги. Если velocity упала на 40% за год — это 40% потерянной производительности команды. Если деплой занимает 3 часа вместо 10 минут — это конкретные деньги за рабочее время. Цифры работают лучше, чем «у нас плохая архитектура».

Что такое Strangler Fig Pattern и когда его применять?

Паттерн из книги Мартина Фаулера: новая система постепенно «обволакивает» старую, берет на себя все больше функций, пока старая не перестает использоваться. Подходит для больших систем, где нельзя остановить все и переписать. Не подходит для очень маленьких модулей — там проще прямой рефакторинг.

Архитектурные проблемы — это всегда вина команды?

Нет. Большинство архитектурных проблем — результат правильных решений в прошлом, которые перестали быть правильными с ростом системы. То, что хорошо работало при 10 000 пользователей, ломается при 1 000 000. Это нормальная эволюция. Вина возникает тогда, когда сигналы игнорировались намеренно.

Хочешь работать с нами? Отправь свое резюме

Нажимая на кнопку, вы соглашаетесь с Политикой конфиденциальности персональных данных

Файлы cookie обеспечивают работу наших сервисов. Используя наш сайт, вы соглашаетесь с нашими правилами в отношении этих файлов.