Недавно на проекте завязался спор - "что такое хорошо и что такое плохо?" 🙂
Раньше я во многом смотрел на архитектуру как на правильную структуру системы.
Хорошие границы. Понятная декомпозиция. Контракты между компонентами. Подходящие паттерны. Нормальная модель данных. Аккуратные диаграммы.
Все это по-прежнему важно. Но со временем я перестал считать этого достаточным.
Можно нарисовать очень красивую архитектуру, которая плохо переживает отказ одной зависимости.
• Можно идеально разделить систему на микросервисы и получить распределенный монолит, где любое изменение требует синхронизации пяти команд.
• Можно правильно применить cache-aside и неожиданно изменить договор с пользователем о свежести данных.
• Можно выбрать Kafka там, где она действительно уместна, а через год обнаружить, что никто уже не способен ответить, какую версию данных пользователь должен видеть прямо сейчас.
• Можно построить технически элегантное решение, которое стоит бизнесу в пять раз дороже более скучной альтернативы.
• И можно иметь прекрасную C4-модель системы, которая практически ничего не говорит о том, что произойдет, когда один из квадратиков перестанет работать.
Поэтому сегодня первое, что мне интересно в архитектурном решении, - не количество паттернов и не красота схемы.
Мне интересно другое.
Какие ограничения мы учитывали? От чего сознательно отказались? Где находится цена выбранного решения? Что произойдет при частичном отказе? Как система будет деградировать? Как ее обновлять? Как откатывать изменения? Что станет узким местом при росте нагрузки? Кто будет сопровождать все это через три года?
И особенно важный вопрос: насколько хорошо мы понимаем последствия собственного решения?
Потому что у архитектуры почти никогда нет варианта "правильно".
• Берем Redis - выигрываем latency, платим сложностью: консистентность и инвалидация.
• Переходим на асинхронность - уменьшаем связанность по времени, платим сложностью наблюдения за состоянием операции.
• Дробим систему - получаем независимость компонентов, но добавляем сеть, распределенные отказы и организационную стоимость.
• Оставляем монолит - сохраняем простоту взаимодействия, но со временем начинаем платить за связанность изменений.
Архитектура практически всегда выглядит как:
что именно мы готовы купить и какую цену готовы за это заплатить.
Поэтому хорошая архитектура для меня сегодня - не система, в которой все сделано "по best practices".
Это набор осознанных компромиссов, последствия которых команда понимает и умеет контролировать.
А хорошая архитектурная схема - это уже просто способ этот разговор зафиксировать.