Экспресс-курс · No. 02
Не должность, не звание, не результат экзамена. Способ смотреть на проблему, в которой сегодняшнее решение определяет три следующих года.
31 понятие · схемы почти у каждого · шпаргалка в конце
Что отличает архитектора от инженера. Это не знания, а способ видеть проблему.
Карта курса: 31 понятие в восьми группах
Карта метро: сначала видишь линии целиком, потом едешь по станциям.
Архитектура — это не набор технологий, а набор вопросов, которые надо задать до того, как писать код. Каждый вопрос в индустрии имеет своё английское имя: Trade-offs, Coupling, Idempotency, ADR. Курс собирает их в восемь групп — по ним идут главы 1–8.
Как читать курс
Паспорт: одинаковые поля у всех, поэтому их легко сравнивать.
У каждого понятия одно и то же: английское название (запомни его — это термин, по которому ищут и о котором спрашивают на собеседованиях), образ из жизни, схема и карточка с полями: что это, зачем, пример, ловушка (где обычно ошибаются) и связи с другими понятиями. В конце главы — главный вопрос, в конце курса — чек-листы и шпаргалка.
Problem Framing — сомневаться в задаче, а не только в решении
К врачу пришли с просьбой выписать рецепт. Хороший врач сначала спросит, что болит, и может выяснить, что лекарство было бы неправильным.
Когда тебе говорят «сделай X», инженер спрашивает «как сделать X». Архитектор спрашивает «зачем нужен X, и не решит ли проблему что-то другое». Это и есть problem framing — постановка проблемы. Часто оказывается, что задача поставлена неверно — и решение, которое тебе заказали, через год превратится в проблему.
- Что это
- Найти настоящую проблему за просьбой, прежде чем строить решение.
- Зачем
- Самое дорогое — идеально построить не ту вещь.
- Пример
Просят «добавь выгрузку в Excel». Спрашиваешь «зачем» — оказывается, людям неудобен отчёт в самой системе. Чинить надо отчёт.
- Ловушка
- Сразу отвечать на «как», не спросив «зачем».
- Связи
Даёт варианты для Trade-offs; «ничего не делать» — частый ответ YAGNI.
Long-term Thinking — горизонт в годы и ответственность за последствия
Инженер строит дом для семьи, которая въезжает в субботу. Архитектор спрашивает: «А когда у них родится третий ребёнок? А когда мать переедет к ним? А если они захотят сдавать первый этаж?»
Инженер решает задачу как она поставлена. Архитектор решает задачу как она будет выглядеть через три года. Это значит — закладывать в дизайн возможности, которые ещё не нужны, и сознательно не закладывать те, которые звучат красиво, но никогда не понадобятся.
Если плотник криво забил гвоздь — переделают за день. Если архитектор поставил несущую стену не там — дом не перестроить, в нём придётся жить.
Поэтому архитектор отвечает не за код, а за последствия. Ошибка инженера правится за неделю. Ошибка архитектора компания платит годами — техническим долгом, потерянной командой, упущенными возможностями. Архитектор должен думать до того, как написана первая строка, и иметь смелость остановить разработку, если архитектура не выдерживает реальных требований.
- Что это
- Оценивать решение по тому, как оно будет жить через два-три года.
- Зачем
- Архитектурные ошибки самые дорогие: их оплачивают годами.
- Пример
Выбирая схему базы, спросить: «А что, если клиентов станет в десять раз больше? А если появится второй язык?»
- Ловушка
Путать «думать наперёд» со «строить всё наперёд». Думать — да, строить лишнее — нет.
- Связи
Уравновешивается Simplicity и YAGNI; помогает отличить Reversibility.
Инженер делает вещь правильно. Архитектор делает правильную вещь.
Архитектура — это искусство выбирать, что потерять. Идеальных решений не бывает.
Trade-offs — каждое решение что-то выигрывает и что-то проигрывает
Велосипед быстрее пешехода, но мокнет под дождём. Машина не мокнет, но застревает в пробке. Метро не застревает, но не везёт до двери.
Когда инженер выбирает технологию, он часто ищет «лучшую». Это иллюзия. Архитектор знает: любой выбор — это компромисс (trade-off) по нескольким осям: скорость разработки против поддерживаемости, простота против гибкости, стоимость сейчас против стоимости через три года. Назвать оси и осознанно выбрать — главная архитектурная работа.
- Что это
- Любой выбор что-то даёт и что-то забирает. «Лучшего» варианта нет.
- Зачем
Компромисс, названный вслух, можно обсудить и пересмотреть. Скрытый — нет.
- Пример
Готовый облачный сервис: быстро стартовать (выигрыш), но дороже на объёме и сложнее уйти (проигрыш).
- Ловушка
- Искать «лучшую технологию» вместо подходящей.
- Связи
Записываются в ADR; осознанный проигрыш сегодня — это Technical Debt.
Simplicity (KISS) — простое решение почти всегда правильнее сложного
Швейцарский нож умеет всё, но плохо. Один хороший нож режет лучше всех своих собратьев в швейцарском.
Инженер боится упустить требование и закладывает в систему всё, что только может понадобиться. Архитектор знает: каждая возможность, которой никто не пользуется, — это вечный налог на разработку. Сложность нужно вводить осознанно, когда она оправдана; по умолчанию — простое решение, которое легко поменять. Этот принцип часто называют KISS — Keep It Simple, Stupid.
- Что это
- По умолчанию — самое простое решение, которое решает задачу.
- Зачем
- Простое легко понять, проверить и поменять. Сложное — только терпеть.
- Пример
Нужны фоновые задачи на сто штук в день — хватит таблицы в базе и cron, а не отдельного брокера сообщений.
- Ловушка
- Строить «на всякий случай»: каждая лишняя функция — вечный налог.
- Связи
- Родной брат YAGNI; делает Evolvability дешевле.
Reversibility — решения, которые сложно отменить, требуют больше внимания
В ресторане можно вернуть заказ. На свадьбе нельзя вернуть «да».
Не все архитектурные решения равны по цене ошибки. Выбор языка программирования или базы данных — почти необратим. Выбор библиотеки для логирования — обратим за день. Архитектор тратит непропорционально много времени на необратимые решения и быстро принимает обратимые. В индустрии это часто называют one-way door (дверь в одну сторону) и two-way door (дверь, через которую можно вернуться).
- Что это
- Насколько дорого отменить решение, если оно окажется ошибкой.
- Зачем
- Время на обдумывание надо тратить пропорционально цене ошибки.
- Пример
Библиотека логирования — поменять за день. Основная база данных — годы миграции.
- Ловушка
- Неделями спорить об обратимом и за пять минут выбрать необратимое.
- Связи
Необратимое — повод для ADR; обратимость растёт за Interface и своим слоем над External Dependencies.
Technical Debt — сознательный выбор, а не лень
Кредит на бизнес — это нормально, если ты знаешь, когда и из чего будешь его отдавать. Кредит без плана возврата — путь к банкротству.
Иногда правильно сейчас сделать решение, которое потом придётся переписать. Это и есть технический долг (technical debt). Это нормально. Ненормально — не отдавать себе отчёт, что это долг. Архитектор записывает, какие компромиссы были приняты, почему, и когда их нужно пересмотреть.
- Что это
- Упрощение сейчас, за которое потом придётся заплатить переделкой.
- Зачем
- Иногда скорость сегодня важнее чистоты — это законный обмен.
- Пример
Перед запуском захардкодили одну валюту. Записали: «вернуться, когда появится второй рынок».
- Ловушка
- Долг без записи: никто не помнит, что он есть, а проценты растут.
- Связи
- Это Trade-off, записанный в ADR; гасится через Migration.
Как разложить большую задачу на компоненты, чтобы каждый можно было понять, изменить, заменить отдельно.
Decomposition — главный навык архитектора
Невозможно съесть кита целиком. Можно — если разрезать на куски, которые помещаются в рот.
Большая система непостижима. Декомпозиция (decomposition) — умение разрезать её на части. Хорошая архитектура — это набор маленьких частей, каждую из которых можно понять в одиночку. Если для объяснения одного компонента приходится рассказывать про три других — декомпозиция плохая.
- Что это
- Разрезать систему на части, каждую из которых можно понять отдельно.
- Зачем
Человек держит в голове немного. Маленькие части — можно понять и менять.
- Пример
Интернет-магазин: заказы, оплата, каталог, аккаунты — у каждой части своя ответственность.
- Ловушка
- Резать по технике («все контроллеры тут»), а не по смыслу.
- Связи
Качество разреза меряют Cohesion & Coupling; части общаются через Interface.
Cohesion & Coupling — высокая связность внутри, низкая зацепленность снаружи
Хорошая квартира: кухня внутри объединена логично (плита рядом с раковиной), а с соседями — общая только одна стена.
Внутри одного модуля всё должно быть про одну тему — это высокая связность (high cohesion). Между модулями — минимум контактов, через ясный интерфейс — это низкая зацепленность (low coupling). Если поменял что-то в одном модуле и пришлось трогать пять других — зацепленность между ними слишком высокая.
- Что это
Cohesion — насколько части модуля про одно. Coupling — насколько модули зависят друг от друга.
- Зачем
- Тогда изменение остаётся внутри одного модуля, а не расходится волной.
- Пример
Расчёт налога живёт в «Billing», а не размазан по заказам, письмам и отчётам.
- Ловушка
- «Поменял одно — трогай пять»: явный знак высокой зацепленности.
- Связи
- Мерило для Decomposition; держится на Interface.
Layers & the Dependency Rule — слои про направление зависимостей
Этажи дома: третий этаж стоит на втором, второй на первом, первый на фундаменте. Нельзя ставить фундамент на третий этаж.
В хорошей архитектуре бизнес-логика не знает про базу данных, веб-интерфейс или фреймворк. Внутренние слои не зависят от внешних — это правило зависимостей (dependency rule). Когда нужно сменить базу данных или фреймворк, бизнес-логика остаётся нетронутой. Это Clean Architecture в одной фразе.
- Что это
Зависимости смотрят внутрь: детали знают про ядро, ядро про детали — нет.
- Зачем
- Можно сменить базу или фреймворк, не трогая бизнес-правила.
- Пример
Правило «скидка 10% от трёх товаров» не импортирует ни SQL, ни HTTP — его можно проверить тестом без базы.
- Ловушка
- SQL-запросы и HTTP-ответы прямо в бизнес-логике.
- Связи
Работает через Interface; подробно — в курсе об архитектурных паттернах (Hexagonal, Clean).
Interface over Implementation — интерфейс важнее реализации
Тебе всё равно, какой марки лифт в здании. Важно, чтобы кнопки работали одинаково, двери открывались надёжно, и звук был тихий.
Когда модуль взаимодействует с другим, важен контракт между ними (interface), а не то, как другой устроен изнутри (implementation). Сначала проектируется граница (API, интерфейс класса, схема сообщения), потом — реализация. Меняй реализацию свободно, контракт — только с осознанием последствий.
- Что это
- Сначала проектировать границу между частями, потом то, что внутри.
- Зачем
- Реализацию можно менять свободно, пока контракт не тронут.
- Пример
Интерфейс
sendEmail(to, text): сегодня за ним один почтовый сервис, завтра другой — вызывающий код не меняется.- Ловушка
- Вызывающий лезет во внутренности другого модуля в обход интерфейса.
- Связи
Снаружи системы интерфейс становится API Contract; основа Dependency Rule.
Monolith vs Microservices — вопрос не моды, а зрелости
Один повар на маленькой кухне делает блюдо быстрее, чем десять поваров с переговорами в Slack. Сто блюд в час десять поваров делают лучше.
Монолит (monolith) — одно приложение, которое разворачивается целиком. Микросервисы (microservices) — много маленьких сервисов, каждый со своим деплоем. Микросервисы решают проблемы масштаба организации и нагрузки, а не качества кода. Маленькая команда с микросервисами — это сложность, которую никто не просил. Архитектор начинает с монолита и разделяет его, когда чувствует реальную боль, а не «потому что так модно».
- Что это
- Одно приложение целиком — или много отдельных сервисов.
- Зачем
Микросервисы дают независимый деплой и масштаб для больших команд и нагрузок.
- Пример
Команда из пяти человек делает продукт — монолит. Двадцать команд мешают друг другу на одном деплое — пора делить.
- Ловушка
- Микросервисы ради моды: сеть, сбои и согласованность без пользы.
- Связи
Делить по Decomposition; между сервисами нужны Sync vs Async и Idempotency.
Самая прочная часть системы. Шаблоны кода переписывают; модель данных живёт годами.
Data Model — модель данных переживает всё остальное
Фундамент дома стоит дольше всех стен и крыш, которые на нём построят за столетие.
Языки уйдут, фреймворки сменятся, дизайн интерфейса перерисуют десять раз. Структура данных (data model), заложенная в начале, будет жить — потому что менять её на работающей системе очень дорого. Это первое, на что архитектор тратит время, и последнее, что он спешит зафиксировать.
- Что это
- Какие сущности есть в системе, какие у них поля и связи.
- Зачем
- Это самая долгоживущая часть: её дороже всего менять потом.
- Пример
Решить в начале: у заказа один адрес доставки или несколько? Потом поменять — миграция миллионов строк.
- Ловушка
- Набросать таблицы за вечер и строить на них годами.
- Связи
Где живёт каждый факт — Single Source of Truth; менять её — через Migration.
Single Source of Truth — каждый факт хранится в одном месте
Если в семье у каждого свой список покупок — двое купят молоко, никто не купит хлеб.
Одна и та же информация в двух местах — гарантированный путь к рассинхрону. Принцип единого источника правды (single source of truth, SSOT): архитектор определяет, где живёт каждый факт системы. Если данные дублируются (для скорости, например), нужно явно определить, что — источник правды, а что — кэш или проекция.
- Что это
- У каждого факта одно главное место, всё остальное — копии.
- Зачем
- Когда копии разойдутся, ясно, кому верить.
- Пример
Цена товара живёт в каталоге. Поисковый индекс и кэш на сайте — копии, их пересчитывают из каталога.
- Ловушка
- Две системы считают себя главными для одного и того же поля.
- Связи
- Копии — это Cache и проекции; меньше копий — меньше State.
State — сложность; чем меньше, тем лучше
Чистый стол облегчает работу. Заваленный — заставляет помнить, где что лежит, и постоянно отвлекает.
Каждый кусок состояния (state), который где-то хранится, — это что-то, что может рассинхронизироваться, потеряться, противоречить другому состоянию. Хорошая архитектура стремится к функциям без памяти (stateless) и переменным с коротким временем жизни. Состояние оставляется там, где оно действительно необходимо — обычно в базе данных.
- Что это
- Всё, что система помнит между запросами.
- Зачем
Меньше состояния — меньше мест, где что-то может разойтись или потеряться.
- Пример
Корзину хранят в базе, а не в памяти сервера: сервер перезапустился — корзина цела.
- Ловушка
- Состояние в памяти конкретного сервера: упал сервер — пропали данные.
- Связи
- Stateless-сервисы легко размножать — это Scalability.
Transactions — атомарность намерения
Перевод денег — это два действия, но одно намерение. Либо обе записи произошли, либо ни одной. Половина — катастрофа.
Когда несколько изменений должны произойти как единое целое, нужны транзакции (transactions). Это свойство называют атомарностью (atomicity). Архитектор знает, какие операции в системе атомарны, какие могут провалиться частично, и как с этим жить. В распределённых системах это становится центральной проблемой (двухфазный коммит, сага, идемпотентность).
- Что это
Несколько изменений, которые происходят целиком или не происходят вовсе.
- Зачем
- Иначе система застрянет в «половинном» состоянии.
- Пример
- Перевод: списать у A и зачислить B — в одной транзакции.
- Ловушка
Считать, что транзакция работает через несколько сервисов. Там нужны сага и идемпотентность.
- Связи
Между сервисами опирается на Idempotency; см. паттерн Saga в курсе об архитектурных паттернах.
Cache — вторая правда, и она может лгать
Календарь на холодильнике быстрее, чем заглянуть в телефон. Но если кто-то изменил расписание в телефоне — холодильник уже врёт.
Кеш (cache) даёт скорость, но забирает гарантию свежести. Архитектор всегда понимает: что у нас закешировано, как долго, и что произойдёт, если кеш врёт. Самый сложный вопрос в кешировании — не как добавить кеш, а как его инвалидировать (cache invalidation).
- Что это
- Быстрая копия данных рядом с тем, кто их читает.
- Зачем
- Скорость и меньше нагрузки на источник.
- Пример
Поменяли цену в базе — а в кеше старая. Покупатель видит одну цену, платит другую.
- Ловушка
- Добавить кеш, не решив, когда и как его сбрасывать.
- Связи
- Это копия при Single Source of Truth, а не вторая правда.
Самые большие проблемы рождаются не внутри компонентов, а между ними.
API Contract — граница системы это контракт, а не код
Граница между странами — это не забор, а правила: что можно перевозить, кому въезжать, какой паспорт нужен.
API, схема сообщения, формат файла — это обещание перед всеми, кто этим пользуется. Менять контракт — это менять обещание, и стоит это дорого. Хороший архитектор проектирует контракты так, чтобы их можно было расширять без поломки старых клиентов (добавлять поля, не убирать). Это свойство называют обратной совместимостью (backward compatibility).
- Что это
- Публичное обещание: какие запросы принимаются и что возвращается.
- Зачем
- От него зависят клиенты, которых ты не контролируешь.
- Пример
Добавили в ответ поле
currency— старое приложение его просто не читает. Переименовалиprice— старое приложение упало.- Ловушка
- Менять контракт так же легко, как внутренний код.
- Связи
Внешняя сторона Interface over Implementation; меняется через Migration.
Sync vs Async — выбор связанности во времени
Телефонный звонок: оба должны быть онлайн одновременно. Письмо: получатель прочтёт, когда удобно.
Синхронный вызов (synchronous) связывает два сервиса во времени: если получатель сломан, отправитель тоже встал. Асинхронная связь (asynchronous) через очередь сообщений разрывает эту связь: отправитель кладёт письмо и идёт дальше. Это даёт устойчивость, но добавляет сложность: задержки, дубликаты, порядок.
- Что это
- Ждать ответа сразу (звонок) — или отправить и не ждать (письмо).
- Зачем
- Async отвязывает сервисы: сбой одного не останавливает другой.
- Пример
Оформление заказа — синхронно (покупатель ждёт). Письмо с чеком — асинхронно, через очередь.
- Ловушка
Забыть цену async: задержки, дубликаты, сообщения приходят не по порядку.
- Связи
- Дубликаты требуют Idempotency; часто нужно между микросервисами.
Idempotency — операцию можно повторить безопасно
Лифт нажат на третий этаж. Если десять человек нажмут ту же кнопку ещё раз — лифт всё равно едет на третий, ничего не ломается.
В реальных системах вызовы повторяются: из-за таймаутов, сетевых сбоев, перезапусков. Идемпотентная (idempotent) операция при повторе даёт тот же результат. Операция, которую опасно повторять, — это бомба замедленного действия. Архитектор делает критичные операции (платежи, обработка сообщений) идемпотентными по умолчанию.
- Что это
- Повтор операции даёт тот же результат, что и первый запуск.
- Зачем
- Повторы неизбежны: таймауты, сбои сети, перезапуски.
- Пример
Клиент шлёт платёж с уникальным ключом. Пришёл тот же ключ ещё раз — сервер возвращает прошлый результат, а не списывает снова.
- Ловушка
- «Повторов у нас не бывает» — бывают, просто ты ещё не видел.
- Связи
- Нужна при Async и ретраях; основа надёжности (Reliability).
External Dependencies — внешние зависимости это всегда риск
Если ужин зависит от пиццерии напротив — не страшно, есть запасные варианты. Если зависит от единственного поставщика мяса в городе — критично.
Каждая внешняя система (external dependency) — API, сервис, библиотека — может стать недоступной, медленной или поменять контракт. Архитектор определяет, что произойдёт, когда это случится: вся система упадёт, или продолжит работать с деградацией. Часто стоит изолировать внешнюю зависимость через свой слой (adapter) — чтобы потом её можно было заменить.
- Что это
- Всё, что ты не контролируешь: чужие API, сервисы, библиотеки.
- Зачем
Когда они падают или меняются, твоя система не должна падать вместе с ними.
- Пример
Платёжный провайдер спрятан за своим интерфейсом
PaymentGateway. Сменить провайдера — написать новый адаптер, а не переписывать заказы.- Ловушка
- Вызовы чужого SDK разбросаны по всему коду.
- Связи
Применение Interface over Implementation; часть Reliability (fallback).
Не «что система делает», а «насколько хорошо она это делает». Их называют non-functional requirements (NFR) или quality attributes — то, что заказчик никогда не сформулирует, но обязательно потребует.
Security — не функция, а образ жизни системы
В музее охрана не одна камера у входа, а слои: турникеты, охранники, камеры в каждом зале, замки на витринах.
Безопасность (security) нельзя добавить в конце. Она встраивается на каждом уровне: аутентификация, авторизация, шифрование, изоляция, аудит, минимальные привилегии (least privilege). Такой подход слоями называют defense in depth — защита в глубину. Архитектор думает о ней с первого дня и спрашивает на каждом решении: «А что, если злоумышленник получит сюда доступ?»
- Что это
- Защита на каждом уровне системы, а не один замок на входе.
- Зачем
- Один слой рано или поздно пробьют — остальные должны держать.
- Пример
Сервис отчётов получает доступ к базе только на чтение — даже если его взломают, данные не удалить.
- Ловушка
- «Добавим безопасность перед релизом».
- Связи
- Аудит опирается на Observability; изоляция — на чёткие границы.
Такси на трёх человек не должно везти как скоростной поезд. Скоростной поезд не подойдёт, чтобы заехать в переулок.
«Сделай быстро» — бессмысленное требование. Архитектор формулирует производительность (performance) в числах: сколько запросов в секунду (throughput), какая задержка (latency) терпима, как ведёт себя система под пиком, что происходит при превышении. Оптимизировать раньше времени — потеря; не подумать вообще — катастрофа.
- Что это
- Сколько система выдерживает и как быстро отвечает — в числах.
- Зачем
Без чисел нельзя понять, хватает ли производительности, и где остановиться.
- Пример
«Поиск отвечает быстрее 300 мс при 200 запросах в секунду; в пике — очередь, а не падение».
- Ловушка
- «Сделай быстро» без чисел — и оптимизация того, что не болит.
- Связи
- Рост нагрузки — Scalability; измеряют через Observability.
Scalability — умение расти, не переписываясь
Дом, в котором заложена возможность пристроить второй этаж, расширяется без сноса. Дом без такой возможности — только перестройкой с нуля.
Масштабируемость (scalability) — система должна расти в две стороны: больше пользователей (горизонтально — добавили серверов) и больше функций (модульно — добавили модулей, не сломав старые). Это закладывается в дизайне, а не приделывается потом.
- Что это
- Способность расти по нагрузке и по функциям без переписывания.
- Зачем
- Успешная система растёт — переписывать её на ходу дорого.
- Пример
Stateless-сервис за балансировщиком: выросла нагрузка — добавили ещё три копии.
- Ловушка
- Строить под миллион пользователей, когда их сто.
- Связи
- Держится на State (stateless) и Cohesion & Coupling (модули).
Reliability — поведение системы, когда что-то сломалось
Хороший корабль не тот, который не тонет (таких не бывает), а тот, у которого десять отсеков, и при пробое одного — остальные продолжают плыть.
Любая часть системы рано или поздно сломается. Надёжность (reliability) — не «никогда не ломается», а «переживает сбой». Архитектор не пытается предотвратить поломку — он проектирует, как система переживёт сбой: изоляция отказов, повторные попытки (retries), грациозная деградация (graceful degradation), фолбэки (fallback). Главное правило: сбой одного компонента не должен убить всю систему.
- Что это
- Как система ведёт себя, когда часть её сломалась.
- Зачем
- Сломается всё — вопрос только, утянет ли один сбой всю систему.
- Пример
Упал сервис рекомендаций — магазин показывает «популярное» вместо персонального, но продаёт.
- Ловушка
- Строить так, будто сбоев не будет.
- Связи
Ретраи требуют Idempotency; увидеть сбой помогает Observability.
Observability — нельзя чинить то, чего не видишь
Машина без датчиков топлива, температуры и давления масла. Едет, пока не сломается насмерть.
Наблюдаемость (observability) — система должна сама рассказывать о своём состоянии: логи (logs), метрики (metrics), трассировки (traces). Когда что-то идёт не так в три ночи, у тебя есть минуты, чтобы найти проблему. Если наблюдаемость не заложена с начала — её добавлять поздно: непонятно даже, где смотреть.
- Что это
- Способность понять, что происходит внутри системы, по её сигналам.
- Зачем
- Без сигналов авария ищется часами, вслепую.
- Пример
Метрика показала рост ошибок в 03:00, трассировка — что тормозит внешний API, лог — с какой ошибкой.
- Ловушка
- Добавлять логи после первой большой аварии.
- Связи
Глаза для Reliability и Performance; основа аудита в Security.
Система живёт долго. Её будут менять. Хорошая архитектура — та, которую легко менять.
Evolvability — готовность к изменениям важнее правильности сегодня
В новом городе строят дороги шире, чем нужно сегодня. Через десять лет машин больше, и узкие дороги пришлось бы сносить.
Архитектор не пытается предусмотреть все будущие фичи (это невозможно). Он оставляет возможность их добавить, не ломая существующее. Это свойство называют evolvability — способность системы развиваться. На практике это: ясные границы, расширяемые контракты, отделение «что» от «как».
- Что это
- Насколько дёшево добавить или поменять что-то в системе.
- Зачем
- Требования изменятся точно — неизвестно только, как.
- Пример
Новый способ оплаты добавляется новым адаптером, а не правкой в двадцати местах.
- Ловушка
- Пытаться предугадать все будущие фичи и строить их заранее.
- Связи
Даётся Interface, Cohesion & Coupling, расширяемым API Contract.
Переезд из старого дома в новый — это процесс на месяцы. Нельзя просто выкинуть всё и купить заново.
Когда систему нужно изменить (новая база, новый протокол, новая модель данных) — это не «переписать с нуля», а «провести через переходный период». Это и есть миграция (migration). Реальные системы работают во время изменений. Архитектор думает о пути миграции с самого начала, иначе переход становится невозможным.
- Что это
- Перевод работающей системы со старого на новое — по шагам.
- Зачем
- Реальную систему нельзя выключить на время ремонта.
- Пример
Новая база: сначала пишем в обе, потом читаем из новой, потом выключаем старую.
- Ловушка
- «Перепишем с нуля за квартал» — и два года живём с двумя системами.
- Связи
Так меняют Data Model и API Contract; так гасят Technical Debt.
YAGNI & Deletion — удалять важнее, чем добавлять
Шкаф нельзя расширять бесконечно. Иногда нужно выбросить старое, чтобы поместилось новое.
Любая успешная система со временем обрастает мёртвым кодом, неиспользуемыми фичами, устаревшими интеграциями. Это налог, который платит каждый разработчик каждый день. Архитектор регулярно ставит вопрос: «Что мы можем удалить?» — и иногда это самое полезное архитектурное решение года.
Самая прочная стена — та, которую не пришлось ломать, потому что под неё ничего не подкладывали лишнего.
Иногда правильное архитектурное решение — не делать архитектурного решения. Не вводить уровень абстракции «на будущее». Не разделять монолит «потому что когда-нибудь». Не строить плагинную систему «потому что мало ли». Этот принцип называют YAGNI — You Aren't Gonna Need It, «тебе это не понадобится». Хороший архитектор знает, когда сказать «не сейчас» или «нам это не нужно».
- Что это
Не строить то, что не нужно сейчас, и удалять то, что больше не нужно.
- Зачем
- Лучшая архитектура — та, которая не была нужна: у неё нулевая цена.
- Пример
Удалили интеграцию, которой пользовались два клиента: минус тысяча строк, минус одна зависимость, минус ночные алерты.
- Ловушка
- Абстракции и плагины «потому что мало ли».
- Связи
- Продолжение Simplicity; освобождает место для Evolvability.
Архитектура, которую никто не понимает, не существует. Половина работы — донести.
ADR — архитектурное решение записывается, иначе оно потеряется
Устное завещание исчезает с автором. Записанное — переживает поколения.
Каждое значимое архитектурное решение нужно зафиксировать: что выбрали, какие были альтернативы, почему отказались от них, какие компромиссы приняли. Этот документ нужен не сейчас — а через год, когда придёт новый человек и спросит «а почему так странно сделано?». Стандартный формат — ADR (Architecture Decision Record).
- Что это
- Короткая запись одного архитектурного решения и его причин.
- Зачем
- Через год никто не вспомнит, почему так. Запись — вспомнит.
- Пример
«ADR-007: Postgres, а не MongoDB. Нужны транзакции между заказом и оплатой. Цена — схема жёстче. Пересмотреть, если появятся неструктурированные данные».
- Ловушка
- Записывать только «что», без «почему» и без отвергнутых вариантов.
- Связи
- Сюда пишут Trade-offs, Technical Debt, необратимые решения.
C4 Model — диаграмма стоит тысячи слов
Описать словами, как добраться до дома, — долго и часто бесполезно. Показать карту — секунда.
У архитектора всегда есть диаграмма системы: какие компоненты, как они связаны, где границы. Не идеальная — рабочая. Она нужна, чтобы быстро объяснить новому человеку и чтобы самому видеть систему целиком. Модель C4 (Context, Container, Component, Code) — простая и достаточная для большинства случаев.
- Что это
- Четыре уровня диаграмм — от системы целиком до кода.
- Зачем
- Каждому зрителю — свой масштаб, а не одна схема на всё.
- Пример
Context: магазин, покупатель, платёжный провайдер. Container: веб-приложение, API, база, очередь.
- Ловушка
- Одна огромная схема, где всё на одном уровне и ничего не понятно.
- Связи
- Рисует Decomposition и границы; дополняет ADR.
Хороший врач объясняет диагноз пациенту словами, которые тот понимает. Плохой — медицинскими терминами, после которых пациент кивает и ничего не понимает.
Если архитектор может объяснить решение только другим инженерам — он пропустил половину работы. Бизнес-стороны, продукт, юристы, безопасность — все заинтересованные стороны (stakeholders) должны понимать последствия. Умение перевести техническое решение в бизнес-язык (стоимость, риск, время) — одно из главных умений архитектора.
Хирург, который соглашается на любую просьбу, теряет пациентов. Хороший — отказывает, когда операция убьёт.
Команда часто просит решений, которые звучат разумно, но создают долгосрочные проблемы. Архитектор должен уметь возразить, объяснить риск и иногда настоять на своём — даже когда это непопулярно. Но также — уметь признать, когда сам неправ, и поменять решение, если контраргумент сильнее.
- Что это
- Объяснять решения на языке слушателя: стоимость, риск, время.
- Зачем
- Решение, которое не поняли, не поддержат — или отменят.
- Пример
Не «нам нужна очередь сообщений», а «без этого при сбое почтового сервиса мы теряем заказы — примерно столько-то в месяц».
- Ловушка
- Говорить терминами — или соглашаться на всё, чтобы не спорить.
- Связи
- Опирается на Trade-offs, ADR и C4 Model.
Чек-листы, которые архитектор задаёт себе перед любым решением и в конце дня. И все понятия курса на одной странице.
- Какая проблема решается на самом деле? Не задача, как она поставлена, а проблема за ней.
- Какие есть альтернативы? Минимум три, включая «ничего не делать».
- Что я этим выбором теряю? Назвать минимум два недостатка.
- Насколько это решение обратимо? Если обратимо — можно решать быстро. Если нет — нужно больше думать.
- Как это будет выглядеть через два-три года? Не идеально, а реалистично.
- Кто, кроме меня, должен это решение понять? И как я ему объясню.
- Что в этой системе самое хрупкое? Что сломается первым под нагрузкой?
- Какие изменения сделать легко, а какие — больно? Это и есть мера качества архитектуры.
- Где живёт правда о каждом важном факте? И где её копии — кеши, реплики, проекции.
- Какие границы между компонентами явные, а какие — случайные? Случайные — это технический долг.
- Что произойдёт, если сломается каждая внешняя зависимость? Поочерёдно.
- Если бы я начал заново сегодня, что бы сделал иначе? Это направление эволюции.
- Ты тратишь больше времени на обсуждение и проектирование, чем на код.
- Ты часто спрашиваешь «а зачем», а не сразу «как».
- Ты называешь компромиссы вслух, а не пытаешься их спрятать.
- Ты пишешь документы и диаграммы чаще, чем большинство.
- Ты видишь систему целиком и можешь объяснить любую её часть в контексте.
- Ты думаешь о людях, которые будут с этим работать через год — и пишешь так, чтобы им было удобно.
- Ты иногда отказываешься от красивой технологии, потому что она не нужна.
Как понятия связаны между собой
Ящик с инструментами: молоток не работает без гвоздей, а гвозди — без молотка.
Понятия курса не живут поодиночке. Решение начинается с Problem Framing, взвешивается как Trade-off, проверяется на Reversibility и записывается в ADR. Систему режут Decomposition, качество разреза меряют Cohesion & Coupling, части встречаются на Interface. Копии данных живут при Single Source of Truth, а повторы в асинхронном мире требуют Idempotency.
Шпаргалка: все 31 понятие
Мышление
- Problem Framingпостановка проблемы
Сначала «зачем», потом «как». Найди проблему за просьбой.
- Long-term Thinkingдолгий горизонт
Смотри на решение через три года; отвечай за последствия, а не за код.
Компромиссы и решения
- Trade-offsкомпромиссы
Любой выбор что-то даёт и что-то забирает. Назови оси вслух.
- SimplicityKISS
По умолчанию — простое. Лишняя функция — вечный налог.
- Reversibilityone-way / two-way door
Обратимое решай быстро, необратимое — медленно.
- Technical Debtтехнический долг
Упрощение сейчас, оплата потом. Нормально, если записано.
Системное проектирование
- Decompositionдекомпозиция
Части, каждую из которых можно понять в одиночку.
- Cohesion & Couplingсвязность и зацепленность
Внутри модуля — про одно; между модулями — минимум связей.
- Dependency Ruleслои, Clean Architecture
Зависимости смотрят внутрь: бизнес-логика не знает про базу и фреймворк.
- Interface over Implementationсначала контракт
Сначала граница, потом реализация. Реализацию меняй свободно.
- Monolith vs Microservicesмонолит или микросервисы
Начинай с монолита, дели, когда реально болит.
Данные и состояние
- Data Modelмодель данных
Живёт дольше кода. Думай над ней первой.
- Single Source of TruthSSOT
У каждого факта одно главное место, остальное — копии.
- Statestateless vs stateful
Состояние — сложность. Держи его мало и в одном месте.
- Transactionatomicity
Несколько изменений — целиком или никак.
- Cachecache invalidation
Быстрая копия, которая может врать. Главное — когда сбрасывать.
Связи и границы
- API Contractbackward compatibility
Обещание клиентам. Расширяй, не убирай.
- Sync vs Asyncзвонок или письмо
Sync связывает во времени; async — устойчивее, но с задержками и дубликатами.
- Idempotencyидемпотентность
Повтор даёт тот же результат. Обязательно для платежей и сообщений.
- External Dependenciesсвой adapter
Чужое упадёт и поменяется. Спрячь за своим слоем, продумай деградацию.
Нефункциональные требования
- Securitydefense in depth
Защита слоями с первого дня, минимальные привилегии.
- Performancelatency, throughput
Не «быстро», а числа: нагрузка, задержка, поведение в пике.
- Scalabilityгоризонтально и модульно
Расти серверами и модулями, не переписываясь.
- Reliabilityfault tolerance
Сбой одной части не должен убить всю систему.
- Observabilitylogs, metrics, traces
Система сама рассказывает о себе. Закладывай с начала.
Эволюция
- Evolvabilityготовность к изменениям
Оставь место для нового, не угадывая его заранее.
- Migrationпереходный период
Не «переписать с нуля», а провести систему через переход.
- YAGNI & DeletionYou Aren't Gonna Need It
Не строй лишнее, удаляй ненужное.
Коммуникация
- ADRArchitecture Decision Record
Что выбрали, альтернативы, почему, какой ценой.
- C4 ModelContext · Container · Component · Code
Диаграммы системы на четырёх уровнях приближения.
- Stakeholder Communicationобъяснить и сказать «нет»
Говори языком стоимости, риска и времени; умей возразить и признать ошибку.
Архитектор — это не тот, кто знает больше. Это тот, кто думает дольше до того, как начнёт делать.