# Архитектор — это образ мышления

Экспресс-курс архитектора программного обеспечения. 31 понятие — Trade-offs, Technical Debt, Coupling, Single Source of Truth, Idempotency, ADR, C4 и другие — у каждого английское название, образ из жизни, схема и карточка. Девять глав о том, как смотреть на проблему, в которой сегодняшнее решение определяет следующие три года. В конце — шпаргалка по всем понятиям.

- **Author:** Фёдор Чищин
- **Level:** intro
- **Reading time:** ~35 минут чтения
- **Published:** 2026-05-12
- **Source:** https://fedorthinks.com/ru/learn/software-architect-express

---

## 1. Мышление архитектора

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

### Карта курса: 31 понятие в восьми группах

> Карта метро: сначала видишь линии целиком, потом едешь по станциям.

Архитектура — это не набор технологий, а набор **вопросов, которые надо задать до того, как писать код**. Каждый вопрос в индустрии имеет своё английское имя: **Trade-offs**, **Coupling**, **Idempotency**, **ADR**. Курс собирает их в восемь групп — по ним идут главы 1–8.

_Diagram: Восемь групп понятий — по ним идут главы 1–8._

### Как читать курс

> Паспорт: одинаковые поля у всех, поэтому их легко сравнивать.

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

### Problem Framing — сомневаться в задаче, а не только в решении

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

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

_Diagram: Сначала «зачем?», потом настоящая проблема, потом варианты — включая «ничего не делать»._

#### Problem Framing (постановка проблемы)

- **Что это:** Найти настоящую проблему за просьбой, прежде чем строить решение.
- **Зачем:** Самое дорогое — идеально построить не ту вещь.
- **Пример:** Просят «добавь выгрузку в Excel». Спрашиваешь «зачем» — оказывается, людям неудобен отчёт в самой системе. Чинить надо отчёт.
- **Ловушка:** Сразу отвечать на «как», не спросив «зачем».
- **Связи:** Даёт варианты для **Trade-offs**; «ничего не делать» — частый ответ **YAGNI**.

### Long-term Thinking — горизонт в годы и ответственность за последствия

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

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

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

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

_Diagram: Ошибку в коде чинят за неделю. Ошибку в архитектуре оплачивают годами._

#### Long-term Thinking (долгий горизонт, ownership of consequences)

- **Что это:** Оценивать решение по тому, как оно будет жить через два-три года.
- **Зачем:** Архитектурные ошибки самые дорогие: их оплачивают годами.
- **Пример:** Выбирая схему базы, спросить: «А что, если клиентов станет в десять раз больше? А если появится второй язык?»
- **Ловушка:** Путать «думать наперёд» со «строить всё наперёд». Думать — да, строить лишнее — нет.
- **Связи:** Уравновешивается **Simplicity** и **YAGNI**; помогает отличить **Reversibility**.

> **Главный вопрос архитектора:** «Правильную ли вещь мы вообще строим?»

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

## 2. Компромиссы и решения

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

### Trade-offs — каждое решение что-то выигрывает и что-то проигрывает

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

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

_Diagram: Решение — это точка на нескольких осях сразу. Сдвинулся в одну сторону — потерял в другой._

#### Trade-offs (компромиссы)

- **Что это:** Любой выбор что-то даёт и что-то забирает. «Лучшего» варианта нет.
- **Зачем:** Компромисс, названный вслух, можно обсудить и пересмотреть. Скрытый — нет.
- **Пример:** Готовый облачный сервис: быстро стартовать (выигрыш), но дороже на объёме и сложнее уйти (проигрыш).
- **Ловушка:** Искать «лучшую технологию» вместо подходящей.
- **Связи:** Записываются в **ADR**; осознанный проигрыш сегодня — это **Technical Debt**.

### Simplicity (KISS) — простое решение почти всегда правильнее сложного

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

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

_Diagram: Слева платят за то, чем никто не пользуется. Справа добавляют, когда это правда нужно._

#### Simplicity (KISS, Keep It Simple)

- **Что это:** По умолчанию — самое простое решение, которое решает задачу.
- **Зачем:** Простое легко понять, проверить и поменять. Сложное — только терпеть.
- **Пример:** Нужны фоновые задачи на сто штук в день — хватит таблицы в базе и cron, а не отдельного брокера сообщений.
- **Ловушка:** Строить «на всякий случай»: каждая лишняя функция — вечный налог.
- **Связи:** Родной брат **YAGNI**; делает **Evolvability** дешевле.

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

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

Не все архитектурные решения равны по цене ошибки. Выбор языка программирования или базы данных — **почти необратим**. Выбор библиотеки для логирования — обратим за день. Архитектор тратит непропорционально много времени на необратимые решения и быстро принимает обратимые. В индустрии это часто называют **one-way door** (дверь в одну сторону) и **two-way door** (дверь, через которую можно вернуться).

_Diagram: Обратимое решай быстро. Необратимое — медленно и с записью «почему»._

#### Reversibility (one-way / two-way door)

- **Что это:** Насколько дорого отменить решение, если оно окажется ошибкой.
- **Зачем:** Время на обдумывание надо тратить пропорционально цене ошибки.
- **Пример:** Библиотека логирования — поменять за день. Основная база данных — годы миграции.
- **Ловушка:** Неделями спорить об обратимом и за пять минут выбрать необратимое.
- **Связи:** Необратимое — повод для **ADR**; обратимость растёт за **Interface** и своим слоем над **External Dependencies**.

### Technical Debt — сознательный выбор, а не лень

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

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

_Diagram: Записанный долг гасят по плану. Незаписанный копит проценты — команда замедляется каждый месяц._

#### Technical Debt (технический долг)

- **Что это:** Упрощение сейчас, за которое потом придётся заплатить переделкой.
- **Зачем:** Иногда скорость сегодня важнее чистоты — это законный обмен.
- **Пример:** Перед запуском захардкодили одну валюту. Записали: «вернуться, когда появится второй рынок».
- **Ловушка:** Долг без записи: никто не помнит, что он есть, а проценты растут.
- **Связи:** Это **Trade-off**, записанный в **ADR**; гасится через **Migration**.

> **Вопрос на каждое решение:** «Что я выбираю — и что я этим теряю?»

## 3. Системное проектирование

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

### Decomposition — главный навык архитектора

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

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

_Diagram: Целую систему не понять. Части, каждая из которых объясняется сама по себе, — можно._

#### Decomposition (декомпозиция)

- **Что это:** Разрезать систему на части, каждую из которых можно понять отдельно.
- **Зачем:** Человек держит в голове немного. Маленькие части — можно понять и менять.
- **Пример:** Интернет-магазин: заказы, оплата, каталог, аккаунты — у каждой части своя ответственность.
- **Ловушка:** Резать по технике («все контроллеры тут»), а не по смыслу.
- **Связи:** Качество разреза меряют **Cohesion & Coupling**; части общаются через **Interface**.

### Cohesion & Coupling — высокая связность внутри, низкая зацепленность снаружи

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

Внутри одного модуля всё должно быть **про одну тему** — это **высокая связность (high cohesion)**. Между модулями — минимум контактов, через ясный интерфейс — это **низкая зацепленность (low coupling)**. Если поменял что-то в одном модуле и пришлось трогать пять других — зацепленность между ними слишком высокая.

_Diagram: Слева каждый модуль про одно и связь одна. Справа всё вперемешку и всё зацеплено за всё._

#### Cohesion & Coupling (связность и зацепленность)

- **Что это:** **Cohesion** — насколько части модуля про одно. **Coupling** — насколько модули зависят друг от друга.
- **Зачем:** Тогда изменение остаётся внутри одного модуля, а не расходится волной.
- **Пример:** Расчёт налога живёт в «Billing», а не размазан по заказам, письмам и отчётам.
- **Ловушка:** «Поменял одно — трогай пять»: явный знак высокой зацепленности.
- **Связи:** Мерило для **Decomposition**; держится на **Interface**.

### Layers & the Dependency Rule — слои про направление зависимостей

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

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

_Diagram: Детали (UI, база, фреймворк) зависят от бизнес-логики, а не наоборот._

#### Dependency Rule (слои, Clean Architecture)

- **Что это:** Зависимости смотрят внутрь: детали знают про ядро, ядро про детали — нет.
- **Зачем:** Можно сменить базу или фреймворк, не трогая бизнес-правила.
- **Пример:** Правило «скидка 10% от трёх товаров» не импортирует ни SQL, ни HTTP — его можно проверить тестом без базы.
- **Ловушка:** SQL-запросы и HTTP-ответы прямо в бизнес-логике.
- **Связи:** Работает через **Interface**; подробно — в курсе об архитектурных паттернах (Hexagonal, Clean).

### Interface over Implementation — интерфейс важнее реализации

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

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

_Diagram: Вызывающий видит только интерфейс. Реализацию за ним можно заменить._

#### Interface over Implementation (сначала контракт)

- **Что это:** Сначала проектировать границу между частями, потом то, что внутри.
- **Зачем:** Реализацию можно менять свободно, пока контракт не тронут.
- **Пример:** Интерфейс `sendEmail(to, text)`: сегодня за ним один почтовый сервис, завтра другой — вызывающий код не меняется.
- **Ловушка:** Вызывающий лезет во внутренности другого модуля в обход интерфейса.
- **Связи:** Снаружи системы интерфейс становится **API Contract**; основа **Dependency Rule**.

### Monolith vs Microservices — вопрос не моды, а зрелости

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

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

_Diagram: Начинают с монолита. Делят, когда реально болит: растёт команда или нагрузка._

#### Monolith vs Microservices (монолит или микросервисы)

- **Что это:** Одно приложение целиком — или много отдельных сервисов.
- **Зачем:** Микросервисы дают независимый деплой и масштаб для больших команд и нагрузок.
- **Пример:** Команда из пяти человек делает продукт — монолит. Двадцать команд мешают друг другу на одном деплое — пора делить.
- **Ловушка:** Микросервисы ради моды: сеть, сбои и согласованность без пользы.
- **Связи:** Делить по **Decomposition**; между сервисами нужны **Sync vs Async** и **Idempotency**.

> **Тест декомпозиции:** «Могу ли я объяснить один компонент, не упоминая остальные?»

## 4. Данные и состояние

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

### Data Model — модель данных переживает всё остальное

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

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

_Diagram: Интерфейс перерисуют много раз, фреймворк и язык сменятся — модель данных останется._

#### Data Model (модель данных)

- **Что это:** Какие сущности есть в системе, какие у них поля и связи.
- **Зачем:** Это самая долгоживущая часть: её дороже всего менять потом.
- **Пример:** Решить в начале: у заказа один адрес доставки или несколько? Потом поменять — миграция миллионов строк.
- **Ловушка:** Набросать таблицы за вечер и строить на них годами.
- **Связи:** Где живёт каждый факт — **Single Source of Truth**; менять её — через **Migration**.

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

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

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

_Diagram: Запись идёт только в источник правды; кэш, реплика и проекция — производные копии._

#### Single Source of Truth (SSOT, единый источник правды)

- **Что это:** У каждого факта одно главное место, всё остальное — копии.
- **Зачем:** Когда копии разойдутся, ясно, кому верить.
- **Пример:** Цена товара живёт в каталоге. Поисковый индекс и кэш на сайте — копии, их пересчитывают из каталога.
- **Ловушка:** Две системы считают себя главными для одного и того же поля.
- **Связи:** Копии — это **Cache** и проекции; меньше копий — меньше **State**.

### State — сложность; чем меньше, тем лучше

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

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

_Diagram: Экземпляры приложения ничего не помнят — всё состояние в одном месте, в базе._

#### State (stateless vs stateful)

- **Что это:** Всё, что система помнит между запросами.
- **Зачем:** Меньше состояния — меньше мест, где что-то может разойтись или потеряться.
- **Пример:** Корзину хранят в базе, а не в памяти сервера: сервер перезапустился — корзина цела.
- **Ловушка:** Состояние в памяти конкретного сервера: упал сервер — пропали данные.
- **Связи:** Stateless-сервисы легко размножать — это **Scalability**.

### Transactions — атомарность намерения

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

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

_Diagram: Либо обе записи, либо ни одной. Половины не бывает._

#### Transaction (транзакция, atomicity)

- **Что это:** Несколько изменений, которые происходят целиком или не происходят вовсе.
- **Зачем:** Иначе система застрянет в «половинном» состоянии.
- **Пример:** Перевод: списать у A и зачислить B — в одной транзакции.
- **Ловушка:** Считать, что транзакция работает через несколько сервисов. Там нужны сага и идемпотентность.
- **Связи:** Между сервисами опирается на **Idempotency**; см. паттерн Saga в курсе об архитектурных паттернах.

### Cache — вторая правда, и она может лгать

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

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

_Diagram: Кеш отвечает быстро, но после изменения в базе его надо сбросить — иначе он врёт._

#### Cache (кеш, cache invalidation)

- **Что это:** Быстрая копия данных рядом с тем, кто их читает.
- **Зачем:** Скорость и меньше нагрузки на источник.
- **Пример:** Поменяли цену в базе — а в кеше старая. Покупатель видит одну цену, платит другую.
- **Ловушка:** Добавить кеш, не решив, когда и как его сбрасывать.
- **Связи:** Это копия при **Single Source of Truth**, а не вторая правда.

> **Вопрос про любые данные:** «Где источник правды, и что произойдёт, если копии разойдутся?»

## 5. Связи и границы

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

### API Contract — граница системы это контракт, а не код

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

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

_Diagram: Добавить поле — старые клиенты живут. Убрать поле — старые клиенты ломаются._

#### API Contract (контракт, backward compatibility)

- **Что это:** Публичное обещание: какие запросы принимаются и что возвращается.
- **Зачем:** От него зависят клиенты, которых ты не контролируешь.
- **Пример:** Добавили в ответ поле `currency` — старое приложение его просто не читает. Переименовали `price` — старое приложение упало.
- **Ловушка:** Менять контракт так же легко, как внутренний код.
- **Связи:** Внешняя сторона **Interface over Implementation**; меняется через **Migration**.

### Sync vs Async — выбор связанности во времени

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

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

_Diagram: Сверху A ждёт B и падает вместе с ним. Снизу A кладёт сообщение в очередь и идёт дальше._

#### Sync vs Async (синхронно или асинхронно)

- **Что это:** Ждать ответа сразу (звонок) — или отправить и не ждать (письмо).
- **Зачем:** Async отвязывает сервисы: сбой одного не останавливает другой.
- **Пример:** Оформление заказа — синхронно (покупатель ждёт). Письмо с чеком — асинхронно, через очередь.
- **Ловушка:** Забыть цену async: задержки, дубликаты, сообщения приходят не по порядку.
- **Связи:** Дубликаты требуют **Idempotency**; часто нужно между микросервисами.

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

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

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

_Diagram: Один и тот же запрос пришёл три раза — деньги списаны один раз._

#### Idempotency (идемпотентность)

- **Что это:** Повтор операции даёт тот же результат, что и первый запуск.
- **Зачем:** Повторы неизбежны: таймауты, сбои сети, перезапуски.
- **Пример:** Клиент шлёт платёж с уникальным ключом. Пришёл тот же ключ ещё раз — сервер возвращает прошлый результат, а не списывает снова.
- **Ловушка:** «Повторов у нас не бывает» — бывают, просто ты ещё не видел.
- **Связи:** Нужна при **Async** и ретраях; основа надёжности (**Reliability**).

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

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

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

_Diagram: Ядро говорит со своим слоем-адаптером. За ним — поставщик, запасной поставщик или режим деградации._

#### External Dependencies (внешние зависимости, свой adapter)

- **Что это:** Всё, что ты не контролируешь: чужие API, сервисы, библиотеки.
- **Зачем:** Когда они падают или меняются, твоя система не должна падать вместе с ними.
- **Пример:** Платёжный провайдер спрятан за своим интерфейсом `PaymentGateway`. Сменить провайдера — написать новый адаптер, а не переписывать заказы.
- **Ловушка:** Вызовы чужого SDK разбросаны по всему коду.
- **Связи:** Применение **Interface over Implementation**; часть **Reliability** (fallback).

> **Тест границ:** «Что произойдёт, если эта связь оборвётся?»

## 6. Нефункциональные требования

Не «что система делает», а «насколько хорошо она это делает». Их называют non-functional requirements (NFR) или quality attributes — то, что заказчик никогда не сформулирует, но обязательно потребует.

### Security — не функция, а образ жизни системы

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

**Безопасность (security)** нельзя добавить в конце. Она встраивается на каждом уровне: **аутентификация, авторизация, шифрование, изоляция, аудит, минимальные привилегии (least privilege)**. Такой подход слоями называют **defense in depth** — защита в глубину. Архитектор думает о ней с первого дня и спрашивает на каждом решении: «А что, если злоумышленник получит сюда доступ?»

_Diagram: Защита слоями: пройдя один, злоумышленник упирается в следующий._

#### Security (defense in depth, least privilege)

- **Что это:** Защита на каждом уровне системы, а не один замок на входе.
- **Зачем:** Один слой рано или поздно пробьют — остальные должны держать.
- **Пример:** Сервис отчётов получает доступ к базе только на чтение — даже если его взломают, данные не удалить.
- **Ловушка:** «Добавим безопасность перед релизом».
- **Связи:** Аудит опирается на **Observability**; изоляция — на чёткие границы.

### Performance — не «быстро», а «достаточно быстро для нужной нагрузки»

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

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

_Diagram: Требование — это числа: какая задержка терпима и при какой нагрузке. И что будет за пределом._

#### Performance (latency, throughput)

- **Что это:** Сколько система выдерживает и как быстро отвечает — в числах.
- **Зачем:** Без чисел нельзя понять, хватает ли производительности, и где остановиться.
- **Пример:** «Поиск отвечает быстрее 300 мс при 200 запросах в секунду; в пике — очередь, а не падение».
- **Ловушка:** «Сделай быстро» без чисел — и оптимизация того, что не болит.
- **Связи:** Рост нагрузки — **Scalability**; измеряют через **Observability**.

### Scalability — умение расти, не переписываясь

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

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

_Diagram: Две оси роста: вправо — больше серверов, вниз — больше модулей._

#### Scalability (горизонтальное и модульное масштабирование)

- **Что это:** Способность расти по нагрузке и по функциям без переписывания.
- **Зачем:** Успешная система растёт — переписывать её на ходу дорого.
- **Пример:** Stateless-сервис за балансировщиком: выросла нагрузка — добавили ещё три копии.
- **Ловушка:** Строить под миллион пользователей, когда их сто.
- **Связи:** Держится на **State** (stateless) и **Cohesion & Coupling** (модули).

### Reliability — поведение системы, когда что-то сломалось

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

Любая часть системы рано или поздно сломается. **Надёжность (reliability)** — не «никогда не ломается», а «переживает сбой». Архитектор не пытается предотвратить поломку — он **проектирует, как система переживёт сбой**: **изоляция отказов, повторные попытки (retries), грациозная деградация (graceful degradation), фолбэки (fallback)**. Главное правило: _сбой одного компонента не должен убить всю систему_.

_Diagram: Отсеки корабля: пробой одного не топит остальные. Внизу — четыре приёма надёжности._

#### Reliability (надёжность, fault tolerance)

- **Что это:** Как система ведёт себя, когда часть её сломалась.
- **Зачем:** Сломается всё — вопрос только, утянет ли один сбой всю систему.
- **Пример:** Упал сервис рекомендаций — магазин показывает «популярное» вместо персонального, но продаёт.
- **Ловушка:** Строить так, будто сбоев не будет.
- **Связи:** Ретраи требуют **Idempotency**; увидеть сбой помогает **Observability**.

### Observability — нельзя чинить то, чего не видишь

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

**Наблюдаемость (observability)** — система должна **сама рассказывать о своём состоянии**: **логи (logs), метрики (metrics), трассировки (traces)**. Когда что-то идёт не так в три ночи, у тебя есть минуты, чтобы найти проблему. Если наблюдаемость не заложена с начала — её добавлять поздно: непонятно даже, где смотреть.

_Diagram: Три сигнала — логи, метрики, трассировки — превращают ночную аварию в поиск на минуты._

#### Observability (logs, metrics, traces)

- **Что это:** Способность понять, что происходит внутри системы, по её сигналам.
- **Зачем:** Без сигналов авария ищется часами, вслепую.
- **Пример:** Метрика показала рост ошибок в 03:00, трассировка — что тормозит внешний API, лог — с какой ошибкой.
- **Ловушка:** Добавлять логи после первой большой аварии.
- **Связи:** Глаза для **Reliability** и **Performance**; основа аудита в **Security**.

> **Главный нефункциональный вопрос:** «Под какой нагрузкой, в каких условиях, с какой надёжностью?»

## 7. Эволюция системы

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

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

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

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

#### Evolvability (готовность к изменениям)

- **Что это:** Насколько дёшево добавить или поменять что-то в системе.
- **Зачем:** Требования изменятся точно — неизвестно только, как.
- **Пример:** Новый способ оплаты добавляется новым адаптером, а не правкой в двадцати местах.
- **Ловушка:** Пытаться предугадать все будущие фичи и строить их заранее.
- **Связи:** Даётся **Interface**, **Cohesion & Coupling**, расширяемым **API Contract**.

### Migration — первоклассная задача, а не «потом сделаем»

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

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

_Diagram: Старое и новое живут рядом, трафик переходит постепенно, система не останавливается._

#### Migration (миграция, переходный период)

- **Что это:** Перевод работающей системы со старого на новое — по шагам.
- **Зачем:** Реальную систему нельзя выключить на время ремонта.
- **Пример:** Новая база: сначала пишем в обе, потом читаем из новой, потом выключаем старую.
- **Ловушка:** «Перепишем с нуля за квартал» — и два года живём с двумя системами.
- **Связи:** Так меняют **Data Model** и **API Contract**; так гасят **Technical Debt**.

### YAGNI & Deletion — удалять важнее, чем добавлять

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

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

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

Иногда правильное архитектурное решение — **не делать архитектурного решения**. Не вводить уровень абстракции «на будущее». Не разделять монолит «потому что когда-нибудь». Не строить плагинную систему «потому что мало ли». Этот принцип называют **YAGNI** — _You Aren't Gonna Need It_, «тебе это не понадобится». Хороший архитектор знает, когда сказать «не сейчас» или «нам это не нужно».

#### YAGNI & Deletion (You Aren't Gonna Need It)

- **Что это:** Не строить то, что не нужно сейчас, и удалять то, что больше не нужно.
- **Зачем:** Лучшая архитектура — та, которая не была нужна: у неё нулевая цена.
- **Пример:** Удалили интеграцию, которой пользовались два клиента: минус тысяча строк, минус одна зависимость, минус ночные алерты.
- **Ловушка:** Абстракции и плагины «потому что мало ли».
- **Связи:** Продолжение **Simplicity**; освобождает место для **Evolvability**.

> **Тест эволюции:** «Сколько кода придётся переписать, если требования изменятся?»

## 8. Коммуникация и документация

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

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

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

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

_Diagram: Одна короткая страница на одно решение: контекст, выбор, альтернативы, компромиссы, когда пересмотреть._

#### ADR (Architecture Decision Record)

- **Что это:** Короткая запись одного архитектурного решения и его причин.
- **Зачем:** Через год никто не вспомнит, почему так. Запись — вспомнит.
- **Пример:** «ADR-007: Postgres, а не MongoDB. Нужны транзакции между заказом и оплатой. Цена — схема жёстче. Пересмотреть, если появятся неструктурированные данные».
- **Ловушка:** Записывать только «что», без «почему» и без отвергнутых вариантов.
- **Связи:** Сюда пишут **Trade-offs**, **Technical Debt**, необратимые решения.

### C4 Model — диаграмма стоит тысячи слов

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

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

_Diagram: Четыре уровня приближения — как карта: страна, город, улица, дом._

#### C4 Model (Context · Container · Component · Code)

- **Что это:** Четыре уровня диаграмм — от системы целиком до кода.
- **Зачем:** Каждому зрителю — свой масштаб, а не одна схема на всё.
- **Пример:** Context: магазин, покупатель, платёжный провайдер. Container: веб-приложение, API, база, очередь.
- **Ловушка:** Одна огромная схема, где всё на одном уровне и ничего не понятно.
- **Связи:** Рисует **Decomposition** и границы; дополняет **ADR**.

### Stakeholder Communication — объяснить неинженеру и уметь сказать «нет»

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

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

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

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

#### Stakeholder Communication (объяснить и сказать «нет»)

- **Что это:** Объяснять решения на языке слушателя: стоимость, риск, время.
- **Зачем:** Решение, которое не поняли, не поддержат — или отменят.
- **Пример:** Не «нам нужна очередь сообщений», а «без этого при сбое почтового сервиса мы теряем заказы — примерно столько-то в месяц».
- **Ловушка:** Говорить терминами — или соглашаться на всё, чтобы не спорить.
- **Связи:** Опирается на **Trade-offs**, **ADR** и **C4 Model**.

> **Тест коммуникации:** «Может ли новый человек через полгода понять, почему так сделано?»

## 9. Самопроверка и шпаргалка

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

#### Перед любым архитектурным решением

- **Какая проблема решается на самом деле?** Не задача, как она поставлена, а проблема за ней.
- **Какие есть альтернативы?** Минимум три, включая «ничего не делать».
- **Что я этим выбором теряю?** Назвать минимум два недостатка.
- **Насколько это решение обратимо?** Если обратимо — можно решать быстро. Если нет — нужно больше думать.
- **Как это будет выглядеть через два-три года?** Не идеально, а реалистично.
- **Кто, кроме меня, должен это решение понять?** И как я ему объясню.

#### При взгляде на любую систему

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

#### Признаки, что ты мыслишь как архитектор

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

### Как понятия связаны между собой

> Ящик с инструментами: молоток не работает без гвоздей, а гвозди — без молотка.

Понятия курса не живут поодиночке. Решение начинается с **Problem Framing**, взвешивается как **Trade-off**, проверяется на **Reversibility** и записывается в **ADR**. Систему режут **Decomposition**, качество разреза меряют **Cohesion & Coupling**, части встречаются на **Interface**. Копии данных живут при **Single Source of Truth**, а повторы в асинхронном мире требуют **Idempotency**.

_Diagram: Три цепочки: как принимать решения, как резать систему, как жить с данными и сбоями._

## Шпаргалка: все 31 понятие

### Мышление

- **Problem Framing** (постановка проблемы): Сначала «зачем», потом «как». Найди проблему за просьбой.
- **Long-term Thinking** (долгий горизонт): Смотри на решение через три года; отвечай за последствия, а не за код.

### Компромиссы и решения

- **Trade-offs** (компромиссы): Любой выбор что-то даёт и что-то забирает. Назови оси вслух.
- **Simplicity** (KISS): По умолчанию — простое. Лишняя функция — вечный налог.
- **Reversibility** (one-way / two-way door): Обратимое решай быстро, необратимое — медленно.
- **Technical Debt** (технический долг): Упрощение сейчас, оплата потом. Нормально, если записано.

### Системное проектирование

- **Decomposition** (декомпозиция): Части, каждую из которых можно понять в одиночку.
- **Cohesion & Coupling** (связность и зацепленность): Внутри модуля — про одно; между модулями — минимум связей.
- **Dependency Rule** (слои, Clean Architecture): Зависимости смотрят внутрь: бизнес-логика не знает про базу и фреймворк.
- **Interface over Implementation** (сначала контракт): Сначала граница, потом реализация. Реализацию меняй свободно.
- **Monolith vs Microservices** (монолит или микросервисы): Начинай с монолита, дели, когда реально болит.

### Данные и состояние

- **Data Model** (модель данных): Живёт дольше кода. Думай над ней первой.
- **Single Source of Truth** (SSOT): У каждого факта одно главное место, остальное — копии.
- **State** (stateless vs stateful): Состояние — сложность. Держи его мало и в одном месте.
- **Transaction** (atomicity): Несколько изменений — целиком или никак.
- **Cache** (cache invalidation): Быстрая копия, которая может врать. Главное — когда сбрасывать.

### Связи и границы

- **API Contract** (backward compatibility): Обещание клиентам. Расширяй, не убирай.
- **Sync vs Async** (звонок или письмо): Sync связывает во времени; async — устойчивее, но с задержками и дубликатами.
- **Idempotency** (идемпотентность): Повтор даёт тот же результат. Обязательно для платежей и сообщений.
- **External Dependencies** (свой adapter): Чужое упадёт и поменяется. Спрячь за своим слоем, продумай деградацию.

### Нефункциональные требования

- **Security** (defense in depth): Защита слоями с первого дня, минимальные привилегии.
- **Performance** (latency, throughput): Не «быстро», а числа: нагрузка, задержка, поведение в пике.
- **Scalability** (горизонтально и модульно): Расти серверами и модулями, не переписываясь.
- **Reliability** (fault tolerance): Сбой одной части не должен убить всю систему.
- **Observability** (logs, metrics, traces): Система сама рассказывает о себе. Закладывай с начала.

### Эволюция

- **Evolvability** (готовность к изменениям): Оставь место для нового, не угадывая его заранее.
- **Migration** (переходный период): Не «переписать с нуля», а провести систему через переход.
- **YAGNI & Deletion** (You Aren't Gonna Need It): Не строй лишнее, удаляй ненужное.

### Коммуникация

- **ADR** (Architecture Decision Record): Что выбрали, альтернативы, почему, какой ценой.
- **C4 Model** (Context · Container · Component · Code): Диаграммы системы на четырёх уровнях приближения.
- **Stakeholder Communication** (объяснить и сказать «нет»): Говори языком стоимости, риска и времени; умей возразить и признать ошибку.

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

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

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