← Назад к блогу

«Нормально делай — нормально будет»: архитектура как фундамент безболезненной разработки

ArchitectureManagementTechnical DebtLeadershipSCADA

Почему одно неверное решение на старте приводит к экспоненциальному росту техдолга. Размышления о Канемане, Безосе и архитектурных комитетах на примере SCADA.AI.

Анатомия одной катастрофы

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

Одно неверное архитектурное решение, принятое на старте проекта в угоду скорости, приводит к экспоненциальному росту технического долга. Каждый последующий «костыль» требует двух-трёх новых. Локализация проблемы, понимание её корня и принятие решений по исправлению отнимают у разработчиков, аналитиков и руководителей сотни часов.

В SCADA.AI команда столкнулась с этим феноменом наглядно: система была унаследована на версии 1.0.5, когда критические архитектурные решения уже были приняты. В REST API использовалась устаревшая библиотека для установки соединений, не были заложены механизмы кеширования при работе с базой данных и отображении графиков. Результат — деградация производительности, проявившаяся при переходе от тестовых нагрузок к промышленным объёмам.

Технический долг: теория экспоненты

Термин «технический долг» ввёл Уорд Каннингем в 1992 году, чтобы объяснить нетехническим стейкхолдерам экономическую стоимость неполного или незрелого кода. Мартин Фаулер позже расширил концепцию, выделив четыре квадранта техдолга: безрассудный/осмотрительный × преднамеренный/непреднамеренный. Большинство наследственных проблем попадают в категорию «безрассудный + непреднамеренный» — когда решение принимается без осознания его долгосрочных последствий.

Роберт Мартин (Дядюшка Боб) в книге «Clean Architecture» сформулировал цель программной архитектуры так: «минимизировать человеческие ресурсы, необходимые для создания и поддержки требуемой системы». Если усилия по поддержке растут с каждым релизом — архитектура плохая. Если остаются низкими — хорошая.

На практике это проявляется в характерных признаках:

  • Любое изменение требует регрессионного тестирования всей системы (признак сильной связности)
  • Невозможно добавить новую функциональность без рефакторинга старой (нарушение Open/Closed Principle)
  • Разработчики боятся трогать определённые модули (хрупкий код с неявными зависимостями)
  • Время онбординга нового разработчика превышает два месяца (непрозрачная архитектура)

Думай медленно, решение принимай быстро

Даниэль Канеман, нобелевский лауреат по экономике, в книге «Thinking, Fast and Slow» (2011) описал две системы мышления:

  • System 1 — быстрая, интуитивная, автоматическая. Работает без усилий, использует эвристики.
  • System 2 — медленная, аналитическая, требующая концентрации. Включается при решении сложных задач.

Парадокс архитектурных решений в том, что их чаще всего принимают через System 1. «Какая библиотека для HTTP-запросов? Давай requests, все её используют». «Какая БД? SQLite, конечно». «Монолит или микросервисы? Давай монолит, проще». Но архитектура — это стратегическое решение с долгосрочными последствиями, требующее включения System 2.

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

LLM как усилитель архитектурных ошибок

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

В ранних версиях SCADA.AI использовалась монолитная архитектура: все модули делили общее пространство имён, общий системный промпт, общую логику. Языковая модель физически не могла разобраться, где заканчивается один инструмент и начинается другой. Результат: точность вызова нужного инструмента не превышала 60%, модель путалась в контексте, вызывала несуществующие функции, галлюцинировала.

Переход на модульную архитектуру с Module Registry и Tool Executor (подробнее в статье про модульную архитектуру) потребовал трёх месяцев работы команды. Три месяца, которые можно было не тратить, если бы архитектура была заложена правильно с самого начала. Каждый модуль получил одну ответственность, свой системный промпт, чёткие границы — и точность выросла до 95%.

Линус Торвальдс однажды заметил: «Плохие программисты беспокоятся о коде. Хорошие программисты беспокоятся о структурах данных и их взаимосвязях». Архитектура — это именно структура системы и взаимосвязи между её компонентами. Код вторичен.

Двери Безоса: классификация решений

Джефф Безос в Amazon использует концепцию «one-way door» и «two-way door» для классификации решений:

  • One-way door (дверь в одну сторону) — решения, которые почти невозможно отменить. Выбор языка программирования для ядра, архитектурного паттерна, базы данных для production.
  • Two-way door (дверь в обе стороны) — решения, которые легко откатить. Цвет кнопки, название переменной, формат логирования.

По утверждению Безоса, провал многих компаний заключается в том, что они применяют одинаковый процесс принятия решений ко всем типам дверей. Тратят недели на обсуждение цвета кнопки (two-way door) и принимают за пять минут решение о переходе с PostgreSQL на MongoDB (one-way door).

Архитектурные решения — это почти всегда one-way doors. Возврат к точке бифуркации оказывается дороже, чем изначальный правильный выбор. Поэтому такие решения требуют максимального включения System 2.

Архитектурный комитет как институциональная практика

В зрелых инженерных организациях для one-way doors существует формализованная процедура — архитектурный комитет (archcom). В SCADA.AI он проводится при каждом решении об использовании новой технологии или изменении архитектурного паттерна.

Стандартный формат включает пять пунктов:

  1. Проблема. Какую задачу решаем?
  2. Варианты решения. Какие подходы существуют? (минимум три)
  3. Trade-offs каждого варианта. Плюсы, минусы, риски.
  4. Долгосрочные последствия. Как это повлияет на систему через год?
  5. Reversibility. Это one-way door или two-way door?

Ключевые вопросы команде: «Как вы видите решение? Какие проблемы в дальнейшем вы видите? Как это обойти?»

Техлиды и разработчики часто замечают подводные камни, которые руководитель не видит из-за разницы в уровне абстракции. Замечание «эта библиотека не поддерживает async, нам придётся писать обёртки» или «этот паттерн плохо масштабируется, при 10 000 пользователей начнутся проблемы» может сэкономить месяцы работы.

Грейди Буч, один из создателей UML, сформулировал это так: «Архитектура — это дизайн, но не весь дизайн является архитектурой». Архитектура — это решения, которые трудно изменить. Всё остальное — тактика.

Философия подготовки

Конфуций говорил: «Успех зависит от предварительной подготовки, и без такой подготовки обязательно будет провал». В контексте архитектуры ПО подготовка — это не написание кода, а продумывание структуры, выявление рисков, проработка edge cases до того, как написана первая строка.

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

Практические выводы

Признаки плохой архитектуры

  1. Любое изменение требует регрессионного тестирования всей системы
  2. Невозможно добавить новую функциональность без рефакторинга старой
  3. Разработчики боятся трогать определённые модули
  4. Время онбординга нового разработчика превышает два месяца
  5. Количество «костылей» растёт с каждым спринтом

Признаки хорошей архитектуры

  1. Новые модули добавляются без изменения существующих (Open/Closed Principle)
  2. Модули тестируются изолированно (низкая связность, высокие cohesion)
  3. Система масштабируется горизонтально (stateless компоненты, асинхронное взаимодействие)
  4. Новый разработчик начинает контрибьютить через 2-3 недели
  5. Рефакторинг одного модуля не ломает другие (чёткие интерфейсы)

Процесс принятия архитектурных решений

Для one-way doors:

  • Включить System 2 (медленное мышление)
  • Собрать архитектурный комитет
  • Рассмотреть минимум три варианта
  • Проанализировать trade-offs
  • Провести spike/prototype для проверки гипотез
  • Задокументировать решение в Architecture Decision Record (ADR)

Для two-way doors:

  • Решать быстро
  • Не тратить время на долгие обсуждения
  • При ошибке — откатиться и попробовать снова

Инвестиции, а не кредит

Хорошая архитектура — это инвестиция: затраты сейчас ради экономии потом. Плохая архитектура — это кредит: экономия сейчас с процентами потом. И проценты всегда превышают основную сумму.

Семь раз отмерь, один раз отрежь

Эта русская пословица описывает оптимальный подход к архитектуре точнее любых методологий.

Отмерить семь раз:

  1. Понять проблему (не симптом, а корень)
  2. Определить требования (функциональные и нефункциональные)
  3. Рассмотреть варианты (минимум три)
  4. Проанализировать trade-offs каждого варианта
  5. Оценить долгосрочные последствия
  6. Проконсультироваться с командой
  7. Сделать прототип для проверки критических гипотез

Отрезать один раз: Приняв взвешенное решение, реализовать его решительно. Не сомневаться на каждом шаге. Не переделывать на полпути. Довести до конца.

В SCADA.AI v3.0.0 команда потратила две недели на архитектурный дизайн и три месяца на реализацию. В версии 1.0 было потрачено два дня на «давайте просто начнём кодить» и шесть месяцев на борьбу с техническим долгом. Соотношение затрат говорит само за себя.

Заключение

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

Многолетний опыт показывает простую истину: лучше потратить время на старте, чем тратить время, деньги и нервы потом. Лучше включить System 2 и медленно продумать архитектуру, чем быстро наделать костылей и годами их разгребать.

Уорд Каннингем, Мартин Фаулер, Даниэль Канеман, Джефф Безос, Грейди Буч, Линус Торвальдс — все они говорят об одном и том же разными словами: архитектурные решения определяют судьбу проекта.

Поэтому: думай медленно, принимай решения быстро (после того, как подумал) и помни — нормально делай, нормально будет.