Экспресс-курс · No. 02

Не должность, не звание, не результат экзамена. Способ смотреть на проблему, в которой сегодняшнее решение определяет три следующих года.

Только суть · Детали — сам · Образы важнее определений

§ 01

Что отличает архитектора от инженера. Это не знания, а способ видеть проблему.

Архитектор смотрит на десять лет вперёд

Инженер строит дом для семьи, которая въезжает в субботу. Архитектор спрашивает: «А когда у них родится третий ребёнок? А когда мать переедет к ним? А если они захотят сдавать первый этаж?»

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

Архитектор отвечает не за код, а за последствия

Если плотник криво забил гвоздь — переделают за день. Если архитектор поставил несущую стену не там — дом не перестроить, в нём придётся жить.

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

Архитектор сомневается в задаче, а не только в решении

К врачу пришли с просьбой выписать рецепт. Хороший врач сначала спросит, что болит, и может выяснить, что лекарство было бы неправильным.

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

Инженер делает вещь правильно. Архитектор делает правильную вещь.

§ 02

Архитектура — это искусство выбирать, что потерять. Идеальных решений не бывает.

Каждое решение что-то выигрывает и что-то проигрывает

Велосипед быстрее пешехода, но мокнет под дождём. Машина не мокнет, но застревает в пробке. Метро не застревает, но не везёт до двери.

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

Простое решение почти всегда правильнее сложного

Швейцарский нож умеет всё, но плохо. Один хороший нож режет лучше всех своих собратьев в швейцарском.

Инженер боится упустить требование и закладывает в систему всё, что только может понадобиться. Архитектор знает: каждая возможность, которой никто не пользуется, — это вечный налог на разработку. Сложность нужно вводить осознанно, когда она оправдана; по умолчанию — простое решение, которое легко поменять.

Решения, которые сложно отменить, требуют больше внимания

В ресторане можно вернуть заказ. На свадьбе нельзя вернуть «да».

Не все архитектурные решения равны по цене ошибки. Выбор языка программирования или базы данных — почти необратим. Выбор библиотеки для логирования — обратим за день. Архитектор тратит непропорционально много времени на необратимые решения и быстро принимает обратимые.

Технический долг — это сознательный выбор, а не лень

Кредит на бизнес — это нормально, если ты знаешь, когда и из чего будешь его отдавать. Кредит без плана возврата — путь к банкротству.

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

§ 03

Как разложить большую задачу на компоненты, чтобы каждый можно было понять, изменить, заменить отдельно.

Декомпозиция — главный навык архитектора

Невозможно съесть кита целиком. Можно — если разрезать на куски, которые помещаются в рот.

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

Высокая связность внутри, низкая связность снаружи

Хорошая квартира: кухня внутри объединена логично (плита рядом с раковиной), а с соседями — общая только одна стена.

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

Слои — это про направление зависимостей

Этажи дома: третий этаж стоит на втором, второй на первом, первый на фундаменте. Нельзя ставить фундамент на третий этаж.

В хорошей архитектуре бизнес-логика не знает про базу данных, веб-интерфейс или фреймворк. Внутренние слои не зависят от внешних. Когда нужно сменить базу данных или фреймворк, бизнес-логика остаётся нетронутой. Это Clean Architecture в одной фразе.

Интерфейс важнее реализации

Тебе всё равно, какой марки лифт в здании. Важно, чтобы кнопки работали одинаково, двери открывались надёжно, и звук был тихий.

Когда модуль взаимодействует с другим, важен контракт между ними, а не то, как другой устроен изнутри. Сначала проектируется граница (API, интерфейс класса, схема сообщения), потом — реализация. Меняй реализацию свободно, контракт — только с осознанием последствий.

Монолит или микросервисы — вопрос не моды, а зрелости

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

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

§ 04

Самая прочная часть системы. Шаблоны кода переписывают; модель данных живёт годами.

Модель данных переживает всё остальное

Фундамент дома стоит дольше всех стен и крыш, которые на нём построят за столетие.

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

Single source of truth — каждый факт хранится в одном месте

Если в семье у каждого свой список покупок — двое купят молоко, никто не купит хлеб.

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

Состояние — это сложность; чем меньше, тем лучше

Чистый стол облегчает работу. Заваленный — заставляет помнить, где что лежит, и постоянно отвлекает.

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

Транзакции — это про атомарность намерения

Перевод денег — это два действия, но одно намерение. Либо обе записи произошли, либо ни одной. Половина — катастрофа.

Когда несколько изменений должны произойти как единое целое, нужны транзакции. Архитектор знает, какие операции в системе атомарны, какие могут провалиться частично, и как с этим жить. В распределённых системах это становится центральной проблемой (двухфазный коммит, сага, идемпотентность).

Кеш — это вторая правда, и она может лгать

Календарь на холодильнике быстрее, чем заглянуть в телефон. Но если кто-то изменил расписание в телефоне — холодильник уже врёт.

Кеш даёт скорость, но забирает гарантию свежести. Архитектор всегда понимает: что у нас закешировано, как долго, и что произойдёт, если кеш врёт. Самый сложный вопрос в кешировании — не как добавить кеш, а как его инвалидировать.

§ 05

Самые большие проблемы рождаются не внутри компонентов, а между ними.

Граница системы — это контракт, а не код

Граница между странами — это не забор, а правила: что можно перевозить, кому въезжать, какой паспорт нужен.

API, схема сообщения, формат файла — это обещание перед всеми, кто этим пользуется. Менять контракт — это менять обещание, и стоит это дорого. Хороший архитектор проектирует контракты так, чтобы их можно было расширять без поломки старых клиентов (добавлять поля, не убирать).

Синхронно или асинхронно — это выбор связанности

Телефонный звонок: оба должны быть онлайн одновременно. Письмо: получатель прочтёт, когда удобно.

Синхронный вызов связывает два сервиса во времени: если получатель сломан, отправитель тоже встал. Очередь сообщений разрывает эту связь: отправитель кладёт письмо и идёт дальше. Это даёт устойчивость, но добавляет сложность: задержки, дубликаты, порядок.

Идемпотентность — операцию можно повторить безопасно

Лифт нажат на третий этаж. Если десять человек нажмут ту же кнопку ещё раз — лифт всё равно едет на третий, ничего не ломается.

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

Внешние зависимости — это всегда риск

Если ужин зависит от пиццерии напротив — не страшно, есть запасные варианты. Если зависит от единственного поставщика мяса в городе — критично.

Каждая внешняя система (API, сервис, библиотека) может стать недоступной, медленной или поменять контракт. Архитектор определяет, что произойдёт, когда это случится: вся система упадёт, или продолжит работать с деградацией. Часто стоит изолировать внешнюю зависимость через свой слой — чтобы потом её можно было заменить.

§ 06

Не «что система делает», а «насколько хорошо она это делает». То, что заказчик никогда не сформулирует, но обязательно потребует.

Безопасность — это не функция, это образ жизни системы

В музее охрана не одна камера у входа, а слои: турникеты, охранники, камеры в каждом зале, замки на витринах.

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

Такси на трёх человек не должно везти как скоростной поезд. Скоростной поезд не подойдёт, чтобы заехать в переулок.

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

Масштабируемость — это умение расти не переписываясь

Дом, в котором заложена возможность пристроить второй этаж, расширяется без сноса. Дом без такой возможности — только перестройкой с нуля.

Система должна расти в две стороны: больше пользователей (горизонтально — добавили серверов) и больше функций (модульно — добавили модулей, не сломав старые). Это закладывается в дизайне, а не приделывается потом.

Надёжность — это поведение системы, когда что-то сломалось

Хороший корабль не тот, который не тонет (таких не бывает), а тот, у которого десять отсеков, и при пробое одного — остальные продолжают плыть.

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

Наблюдаемость — нельзя чинить то, чего не видишь

Машина без датчиков топлива, температуры и давления масла. Едет, пока не сломается насмерть.

Система должна сама рассказывать о своём состоянии: логи, метрики, трассировки. Когда что-то идёт не так в три ночи, у тебя есть минуты, чтобы найти проблему. Если наблюдаемость не заложена с начала — её добавлять поздно: непонятно даже, где смотреть.

§ 07

Система живёт долго. Её будут менять. Хорошая архитектура — та, которую легко менять.

Готовность к изменениям важнее правильности сегодня

В новом городе строят дороги шире, чем нужно сегодня. Через десять лет машин больше, и узкие дороги пришлось бы сносить.

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

Переезд из старого дома в новый — это процесс на месяцы. Нельзя просто выкинуть всё и купить заново.

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

Удалять — важнее, чем добавлять

Шкаф нельзя расширять бесконечно. Иногда нужно выбросить старое, чтобы поместилось новое.

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

Лучшая архитектура — та, которая не была нужна

Самая прочная стена — та, которую не пришлось ломать, потому что под неё ничего не подкладывали лишнего.

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

§ 08

Архитектура, которую никто не понимает, не существует. Половина работы — донести.

Архитектурное решение записывается, иначе оно потеряется

Устное завещание исчезает с автором. Записанное — переживает поколения.

Каждое значимое архитектурное решение нужно зафиксировать: что выбрали, какие были альтернативы, почему отказались от них, какие компромиссы приняли. Этот документ нужен не сейчас — а через год, когда придёт новый человек и спросит «а почему так странно сделано?». Стандартный формат — ADR (Architecture Decision Record).

Диаграмма стоит тысячи слов

Описать словами, как добраться до дома, — долго и часто бесполезно. Показать карту — секунда.

У архитектора всегда есть диаграмма системы: какие компоненты, как они связаны, где границы. Не идеальная — рабочая. Она нужна, чтобы быстро объяснить новому человеку и чтобы самому видеть систему целиком. Принцип C4 (Context, Container, Component, Code) — простой и достаточный для большинства случаев.

Архитектор объясняет так, чтобы понял неинженер

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

Если архитектор может объяснить решение только другим инженерам — он пропустил половину работы. Бизнес-стороны, продукт, юристы, безопасность — все должны понимать последствия. Умение перевести техническое решение в бизнес-язык (стоимость, риск, время) — одно из главных умений архитектора.

Хирург, который соглашается на любую просьбу, теряет пациентов. Хороший — отказывает, когда операция убьёт.

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

§ 09

Чек-листы, которые архитектор задаёт себе перед любым решением и в конце дня.

Перед любым архитектурным решением
  • Какая проблема решается на самом деле? Не задача, как она поставлена, а проблема за ней. - Какие есть альтернативы? Минимум три, включая «ничего не делать». - Что я этим выбором теряю? Назвать минимум два недостатка. - Насколько это решение обратимо? Если обратимо — можно решать быстро. Если нет — нужно больше думать. - Как это будет выглядеть через два-три года? Не идеально, а реалистично. - Кто, кроме меня, должен это решение понять? И как я ему объясню.
При взгляде на любую систему
  • Что в этой системе самое хрупкое? Что сломается первым под нагрузкой? - Какие изменения сделать легко, а какие — больно? Это и есть мера качества архитектуры. - Где живёт правда о каждом важном факте? И где её копии — кеши, реплики, проекции. - Какие границы между компонентами явные, а какие — случайные? Случайные — это технический долг. - Что произойдёт, если сломается каждая внешняя зависимость? Поочерёдно. - Если бы я начал заново сегодня, что бы сделал иначе? Это направление эволюции.
Признаки, что ты мыслишь как архитектор
  • Ты тратишь больше времени на обсуждение и проектирование, чем на код. - Ты часто спрашиваешь «а зачем», а не сразу «как». - Ты называешь компромиссы вслух, а не пытаешься их спрятать.
  • Ты пишешь документы и диаграммы чаще, чем большинство. - Ты видишь систему целиком и можешь объяснить любую её часть в контексте. - Ты думаешь о людях, которые будут с этим работать через год — и пишешь так, чтобы им было удобно. - Ты иногда отказываешься от красивой технологии, потому что она не нужна.

Архитектор — это не тот, кто знает больше. Это тот, кто думает дольше до того, как начнёт делать.

Конец экспресс-курса · 9 разделов · только суть

Дальше — практика. Каждый раздел разворачивается в книги: «Designing Data-Intensive Applications», «Clean Architecture», «Software Architecture in Practice», «System Design Interview». Но прежде чем читать их — задавай себе вопросы из этого документа. Они важнее ответов.