fedorthinks

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

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

31 понятие · схемы почти у каждого · шпаргалка в конце

§ 01

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

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

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

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

1 · MindsetProblem framingLong-term thinking2 · Trade-offsTrade-offsSimplicity (KISS)ReversibilityTechnical debt3 · System designDecompositionCohesion / couplingDependency ruleInterface firstMonolith vs micro4 · Data & stateData modelSource of truthStateTransactionsCache5 · BoundariesAPI contractSync vs asyncIdempotencyExternal deps6 · Quality (NFRs)SecurityPerformanceScalabilityReliabilityObservability7 · EvolutionEvolvabilityMigrationYAGNI / deletion8 · CommunicationADRC4 modelStakeholders
Восемь групп понятий — по ним идут главы 1–8.

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

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

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

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

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

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

“Build X”request as posedWhy?Real problembehind the requestOption Xwhat was askedOption Ya simpler fixDo nothingalso an optionengineer: “how do I build X?” · architect: “why X at all?”
Сначала «зачем?», потом настоящая проблема, потом варианты — включая «ничего не делать».
PracticeProblem Framing· постановка проблемы
Что это
Найти настоящую проблему за просьбой, прежде чем строить решение.
Зачем
Самое дорогое — идеально построить не ту вещь.
Пример

Просят «добавь выгрузку в Excel». Спрашиваешь «зачем» — оказывается, людям неудобен отчёт в самой системе. Чинить надо отчёт.

Ловушка
Сразу отвечать на «как», не спросив «зачем».
Связи

Даёт варианты для Trade-offs; «ничего не делать» — частый ответ YAGNI.

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

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

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

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

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

Engineer’s mistakefixed in a weekArchitect’s mistaketech debt · lost team · missed chancesweekmonth1 year3+ years
Ошибку в коде чинят за неделю. Ошибку в архитектуре оплачивают годами.
ConceptLong-term Thinking· долгий горизонт, ownership of consequences
Что это
Оценивать решение по тому, как оно будет жить через два-три года.
Зачем
Архитектурные ошибки самые дорогие: их оплачивают годами.
Пример

Выбирая схему базы, спросить: «А что, если клиентов станет в десять раз больше? А если появится второй язык?»

Ловушка

Путать «думать наперёд» со «строить всё наперёд». Думать — да, строить лишнее — нет.

Связи

Уравновешивается Simplicity и YAGNI; помогает отличить Reversibility.

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

§ 02

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

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

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

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

every choice is a point on several axesDev speedMaintainabilitySimplicityFlexibilityCost nowCost in 3 years
Решение — это точка на нескольких осях сразу. Сдвинулся в одну сторону — потерял в другой.
ConceptTrade-offs· компромиссы
Что это
Любой выбор что-то даёт и что-то забирает. «Лучшего» варианта нет.
Зачем

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

Пример

Готовый облачный сервис: быстро стартовать (выигрыш), но дороже на объёме и сложнее уйти (проигрыш).

Ловушка
Искать «лучшую технологию» вместо подходящей.
Связи

Записываются в ADR; осознанный проигрыш сегодня — это Technical Debt.

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

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

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

Everything “just in case”featurefeatureunusedunusedunusedunusedSimple by defaultfeaturefeatureadded when really neededunused = a permanent taxeasy to change
Слева платят за то, чем никто не пользуется. Справа добавляют, когда это правда нужно.
PrincipleSimplicity· KISS, Keep It Simple
Что это
По умолчанию — самое простое решение, которое решает задачу.
Зачем
Простое легко понять, проверить и поменять. Сложное — только терпеть.
Пример

Нужны фоновые задачи на сто штук в день — хватит таблицы в базе и cron, а не отдельного брокера сообщений.

Ловушка
Строить «на всякий случай»: каждая лишняя функция — вечный налог.
Связи
Родной брат YAGNI; делает Evolvability дешевле.

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

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

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

Two-way dooreasy to undologging librarydecide fastOne-way doorhard to undoprogramming languagedatabasethink slowspend your time where a mistake is expensive
Обратимое решай быстро. Необратимое — медленно и с записью «почему».
ConceptReversibility· one-way / two-way door
Что это
Насколько дорого отменить решение, если оно окажется ошибкой.
Зачем
Время на обдумывание надо тратить пропорционально цене ошибки.
Пример

Библиотека логирования — поменять за день. Основная база данных — годы миграции.

Ловушка
Неделями спорить об обратимом и за пять минут выбрать необратимое.
Связи

Необратимое — повод для ADR; обратимость растёт за Interface и своим слоем над External Dependencies.

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

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

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

Shortcut nowship fasterRecorded debtwhat · why · whenPaid backplanned rewriteHidden debtnobody wrote it downInterest growsslower every monthconsciousno record
Записанный долг гасят по плану. Незаписанный копит проценты — команда замедляется каждый месяц.
TermTechnical Debt· технический долг
Что это
Упрощение сейчас, за которое потом придётся заплатить переделкой.
Зачем
Иногда скорость сегодня важнее чистоты — это законный обмен.
Пример

Перед запуском захардкодили одну валюту. Записали: «вернуться, когда появится второй рынок».

Ловушка
Долг без записи: никто не помнит, что он есть, а проценты растут.
Связи
Это Trade-off, записанный в ADR; гасится через Migration.
§ 03

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

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

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

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

Whole systemtoo big to understandsplitOrdersexplainable alonePaymentsexplainable aloneCatalogexplainable aloneAccountsexplainable alone
Целую систему не понять. Части, каждая из которых объясняется сама по себе, — можно.
PracticeDecomposition· декомпозиция
Что это
Разрезать систему на части, каждую из которых можно понять отдельно.
Зачем

Человек держит в голове немного. Маленькие части — можно понять и менять.

Пример

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

Ловушка
Резать по технике («все контроллеры тут»), а не по смыслу.
Связи

Качество разреза меряют Cohesion & Coupling; части общаются через Interface.

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

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

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

High cohesion · low couplingOrdersorderline itemstotalsBillinginvoicetaxpaymentone clear interfaceLow cohesion · high couplingModule AordertaxemailModule Binvoicetotalsuserschange one → touch five
Слева каждый модуль про одно и связь одна. Справа всё вперемешку и всё зацеплено за всё.
PrincipleCohesion & Coupling· связность и зацепленность
Что это

Cohesion — насколько части модуля про одно. Coupling — насколько модули зависят друг от друга.

Зачем
Тогда изменение остаётся внутри одного модуля, а не расходится волной.
Пример

Расчёт налога живёт в «Billing», а не размазан по заказам, письмам и отчётам.

Ловушка
«Поменял одно — трогай пять»: явный знак высокой зацепленности.
Связи
Мерило для Decomposition; держится на Interface.

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

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

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

outer layers = detailsdependencies point inward✗ the core never imports the databaseBusiness logicdomain rulesWeb UIDatabaseFramework
Детали (UI, база, фреймворк) зависят от бизнес-логики, а не наоборот.
PrincipleDependency Rule· слои, Clean Architecture
Что это

Зависимости смотрят внутрь: детали знают про ядро, ядро про детали — нет.

Зачем
Можно сменить базу или фреймворк, не трогая бизнес-правила.
Пример

Правило «скидка 10% от трёх товаров» не импортирует ни SQL, ни HTTP — его можно проверить тестом без базы.

Ловушка
SQL-запросы и HTTP-ответы прямо в бизнес-логике.
Связи

Работает через Interface; подробно — в курсе об архитектурных паттернах (Hexagonal, Clean).

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

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

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

CallerInterfacethe contractImpl AtodayImpl Btomorrowthe caller sees only this
Вызывающий видит только интерфейс. Реализацию за ним можно заменить.
PrincipleInterface over Implementation· сначала контракт
Что это
Сначала проектировать границу между частями, потом то, что внутри.
Зачем
Реализацию можно менять свободно, пока контракт не тронут.
Пример

Интерфейс sendEmail(to, text): сегодня за ним один почтовый сервис, завтра другой — вызывающий код не меняется.

Ловушка
Вызывающий лезет во внутренности другого модуля в обход интерфейса.
Связи

Снаружи системы интерфейс становится API Contract; основа Dependency Rule.

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

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

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

Monolithstart heresplit when it hurtsteam scale · loadOrdersown deployBillingown deploySearchown deployUsersown deploy✗ small team + microservices = complexity nobody asked for
Начинают с монолита. Делят, когда реально болит: растёт команда или нагрузка.
ConceptMonolith vs Microservices· монолит или микросервисы
Что это
Одно приложение целиком — или много отдельных сервисов.
Зачем

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

Пример

Команда из пяти человек делает продукт — монолит. Двадцать команд мешают друг другу на одном деплое — пора делить.

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

Делить по Decomposition; между сервисами нужны Sync vs Async и Idempotency.

§ 04

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

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

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

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

UI designFrameworkLanguageData modellaid down at the start, lives for yearsyears →
Интерфейс перерисуют много раз, фреймворк и язык сменятся — модель данных останется.
ConceptData Model· модель данных
Что это
Какие сущности есть в системе, какие у них поля и связи.
Зачем
Это самая долгоживущая часть: её дороже всего менять потом.
Пример

Решить в начале: у заказа один адрес доставки или несколько? Потом поменять — миграция миллионов строк.

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

Где живёт каждый факт — Single Source of Truth; менять её — через Migration.

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

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

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

WritesSource of truthprimary databaseCachederived copyRead replicaderived copyProjectionderived copycopies are derived; writes go to the truth only
Запись идёт только в источник правды; кэш, реплика и проекция — производные копии.
PrincipleSingle Source of Truth· SSOT, единый источник правды
Что это
У каждого факта одно главное место, всё остальное — копии.
Зачем
Когда копии разойдутся, ясно, кому верить.
Пример

Цена товара живёт в каталоге. Поисковый индекс и кэш на сайте — копии, их пересчитывают из каталога.

Ловушка
Две системы считают себя главными для одного и того же поля.
Связи
Копии — это Cache и проекции; меньше копий — меньше State.

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

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

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

App instancestatelessApp instancestatelessApp instancestatelessDatabasestate lives here
Экземпляры приложения ничего не помнят — всё состояние в одном месте, в базе.
ConceptState· stateless vs stateful
Что это
Всё, что система помнит между запросами.
Зачем

Меньше состояния — меньше мест, где что-то может разойтись или потеряться.

Пример

Корзину хранят в базе, а не в памяти сервера: сервер перезапустился — корзина цела.

Ловушка
Состояние в памяти конкретного сервера: упал сервер — пропали данные.
Связи
Stateless-сервисы легко размножать — это Scalability.

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

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

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

one intent = one transactionDebit A−100Credit B+100Both writtencommitNeither writtenrollbackOnly one✗ never allowed
Либо обе записи, либо ни одной. Половины не бывает.
ConceptTransaction· транзакция, atomicity
Что это

Несколько изменений, которые происходят целиком или не происходят вовсе.

Зачем
Иначе система застрянет в «половинном» состоянии.
Пример
Перевод: списать у A и зачислить B — в одной транзакции.
Ловушка

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

Связи

Между сервисами опирается на Idempotency; см. паттерн Saga в курсе об архитектурных паттернах.

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

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

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

AppCachefast · may be staleDatabasesource of truthUpdatereadon missinvalidate!the hard part is not adding a cache — it is invalidating it
Кеш отвечает быстро, но после изменения в базе его надо сбросить — иначе он врёт.
ConceptCache· кеш, cache invalidation
Что это
Быстрая копия данных рядом с тем, кто их читает.
Зачем
Скорость и меньше нагрузки на источник.
Пример

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

Ловушка
Добавить кеш, не решив, когда и как его сбрасывать.
Связи
Это копия при Single Source of Truth, а не вторая правда.
§ 05

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

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

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

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

Client v1Client v2API contracta promiseadd a field✓ old clients fineremove a field✗ breaks v1extend the contract; never take things away
Добавить поле — старые клиенты живут. Убрать поле — старые клиенты ломаются.
ConceptAPI Contract· контракт, backward compatibility
Что это
Публичное обещание: какие запросы принимаются и что возвращается.
Зачем
От него зависят клиенты, которых ты не контролируешь.
Пример

Добавили в ответ поле currency — старое приложение его просто не читает. Переименовали price — старое приложение упало.

Ловушка
Менять контракт так же легко, как внутренний код.
Связи

Внешняя сторона Interface over Implementation; меняется через Migration.

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

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

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

Synchronous: coupled in timeService Awaits…Service BdowncallA is stuck tooAsynchronous: decoupledService Amoves onQueueholds messagesService Breads when readyprice of async: delay · duplicates · ordering
Сверху A ждёт B и падает вместе с ним. Снизу A кладёт сообщение в очередь и идёт дальше.
ConceptSync vs Async· синхронно или асинхронно
Что это
Ждать ответа сразу (звонок) — или отправить и не ждать (письмо).
Зачем
Async отвязывает сервисы: сбой одного не останавливает другой.
Пример

Оформление заказа — синхронно (покупатель ждёт). Письмо с чеком — асинхронно, через очередь.

Ловушка

Забыть цену async: задержки, дубликаты, сообщения приходят не по порядку.

Связи
Дубликаты требуют Idempotency; часто нужно между микросервисами.

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

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

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

Clientsame request ×3 (timeouts)Payment APIidempotentCharged once$100, not $300repeating the operation gives the same result
Один и тот же запрос пришёл три раза — деньги списаны один раз.
ConceptIdempotency· идемпотентность
Что это
Повтор операции даёт тот же результат, что и первый запуск.
Зачем
Повторы неизбежны: таймауты, сбои сети, перезапуски.
Пример

Клиент шлёт платёж с уникальным ключом. Пришёл тот же ключ ещё раз — сервер возвращает прошлый результат, а не списывает снова.

Ловушка
«Повторов у нас не бывает» — бывают, просто ты ещё не видел.
Связи
Нужна при Async и ретраях; основа надёжности (Reliability).

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

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

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

Your coreYour adapterown layerVendor APIcan be slow / downOther vendorswap laterFallbackdegraded mode
Ядро говорит со своим слоем-адаптером. За ним — поставщик, запасной поставщик или режим деградации.
PracticeExternal Dependencies· внешние зависимости, свой adapter
Что это
Всё, что ты не контролируешь: чужие API, сервисы, библиотеки.
Зачем

Когда они падают или меняются, твоя система не должна падать вместе с ними.

Пример

Платёжный провайдер спрятан за своим интерфейсом PaymentGateway. Сменить провайдера — написать новый адаптер, а не переписывать заказы.

Ловушка
Вызовы чужого SDK разбросаны по всему коду.
Связи

Применение Interface over Implementation; часть Reliability (fallback).

§ 06

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

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

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

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

Authentication — who are you?Authorization — what may you do?EncryptionIsolationDataleast privilegeAudit — every access is logged
Защита слоями: пройдя один, злоумышленник упирается в следующий.
QualitySecurity· defense in depth, least privilege
Что это
Защита на каждом уровне системы, а не один замок на входе.
Зачем
Один слой рано или поздно пробьют — остальные должны держать.
Пример

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

Ловушка
«Добавим безопасность перед релизом».
Связи
Аудит опирается на Observability; изоляция — на чёткие границы.

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

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

latencyload (req/s)tolerable latencyexpected peakpast the limit:then what?
Требование — это числа: какая задержка терпима и при какой нагрузке. И что будет за пределом.
QualityPerformance· latency, throughput
Что это
Сколько система выдерживает и как быстро отвечает — в числах.
Зачем

Без чисел нельзя понять, хватает ли производительности, и где остановиться.

Пример

«Поиск отвечает быстрее 300 мс при 200 запросах в секунду; в пике — очередь, а не падение».

Ловушка
«Сделай быстро» без чисел — и оптимизация того, что не болит.
Связи
Рост нагрузки — Scalability; измеряют через Observability.

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

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

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

Systemmore users → add servers (horizontal)serverserverservermore features → add modulesmodulemodulemodule+ new module
Две оси роста: вправо — больше серверов, вниз — больше модулей.
QualityScalability· горизонтальное и модульное масштабирование
Что это
Способность расти по нагрузке и по функциям без переписывания.
Зачем
Успешная система растёт — переписывать её на ходу дорого.
Пример

Stateless-сервис за балансировщиком: выросла нагрузка — добавили ещё три копии.

Ловушка
Строить под миллион пользователей, когда их сто.
Связи
Держится на State (stateless) и Cohesion & Coupling (модули).

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

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

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

bulkheads: one breach stays localokokbreachsealed offokokokIsolationcontain failureRetriestry againFallbackplan BDegradationwork partly
Отсеки корабля: пробой одного не топит остальные. Внизу — четыре приёма надёжности.
QualityReliability· надёжность, fault tolerance
Что это
Как система ведёт себя, когда часть её сломалась.
Зачем
Сломается всё — вопрос только, утянет ли один сбой всю систему.
Пример

Упал сервис рекомендаций — магазин показывает «популярное» вместо персонального, но продаёт.

Ловушка
Строить так, будто сбоев не будет.
Связи

Ретраи требуют Idempotency; увидеть сбой помогает Observability.

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

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

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

SystemLogswhat happenedMetricshow much / how fastTraceswhere time wentYou, at 3 a.m.find it in minutes
Три сигнала — логи, метрики, трассировки — превращают ночную аварию в поиск на минуты.
QualityObservability· logs, metrics, traces
Что это
Способность понять, что происходит внутри системы, по её сигналам.
Зачем
Без сигналов авария ищется часами, вслепую.
Пример

Метрика показала рост ошибок в 03:00, трассировка — что тормозит внешний API, лог — с какой ошибкой.

Ловушка
Добавлять логи после первой большой аварии.
Связи

Глаза для Reliability и Performance; основа аудита в Security.

§ 07

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

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

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

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

QualityEvolvability· готовность к изменениям
Что это
Насколько дёшево добавить или поменять что-то в системе.
Зачем
Требования изменятся точно — неизвестно только, как.
Пример

Новый способ оплаты добавляется новым адаптером, а не правкой в двадцати местах.

Ловушка
Пытаться предугадать все будущие фичи и строить их заранее.
Связи

Даётся Interface, Cohesion & Coupling, расширяемым API Contract.

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

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

Phase 1Old system100% trafficNew system0%Phase 2Old system50%New system50%Phase 3Old system0% → deleteNew system100% trafficthe system keeps running the whole time
Старое и новое живут рядом, трафик переходит постепенно, система не останавливается.
PracticeMigration· миграция, переходный период
Что это
Перевод работающей системы со старого на новое — по шагам.
Зачем
Реальную систему нельзя выключить на время ремонта.
Пример

Новая база: сначала пишем в обе, потом читаем из новой, потом выключаем старую.

Ловушка
«Перепишем с нуля за квартал» — и два года живём с двумя системами.
Связи

Так меняют Data Model и API Contract; так гасят Technical Debt.

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

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

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

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

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

PrincipleYAGNI & Deletion· You Aren't Gonna Need It
Что это

Не строить то, что не нужно сейчас, и удалять то, что больше не нужно.

Зачем
Лучшая архитектура — та, которая не была нужна: у неё нулевая цена.
Пример

Удалили интеграцию, которой пользовались два клиента: минус тысяча строк, минус одна зависимость, минус ночные алерты.

Ловушка
Абстракции и плагины «потому что мало ли».
Связи
Продолжение Simplicity; освобождает место для Evolvability.
§ 08

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

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

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

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

ADR-007: Use PostgresContextDecisionAlternativesWhy not themTrade-offsRevisit whenwritten now,read a yearlater
Одна короткая страница на одно решение: контекст, выбор, альтернативы, компромиссы, когда пересмотреть.
ToolADR· Architecture Decision Record
Что это
Короткая запись одного архитектурного решения и его причин.
Зачем
Через год никто не вспомнит, почему так. Запись — вспомнит.
Пример

«ADR-007: Postgres, а не MongoDB. Нужны транзакции между заказом и оплатой. Цена — схема жёстче. Пересмотреть, если появятся неструктурированные данные».

Ловушка
Записывать только «что», без «почему» и без отвергнутых вариантов.
Связи
Сюда пишут Trade-offs, Technical Debt, необратимые решения.

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

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

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

zoom in →Contextsystem + usersContainerapps · databasesComponentparts of an appCodeclassesone diagram per zoom level — not one giant picture
Четыре уровня приближения — как карта: страна, город, улица, дом.
ToolC4 Model· Context · Container · Component · Code
Что это
Четыре уровня диаграмм — от системы целиком до кода.
Зачем
Каждому зрителю — свой масштаб, а не одна схема на всё.
Пример

Context: магазин, покупатель, платёжный провайдер. Container: веб-приложение, API, база, очередь.

Ловушка
Одна огромная схема, где всё на одном уровне и ничего не понятно.
Связи
Рисует Decomposition и границы; дополняет ADR.

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

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

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

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

PracticeStakeholder Communication· объяснить и сказать «нет»
Что это
Объяснять решения на языке слушателя: стоимость, риск, время.
Зачем
Решение, которое не поняли, не поддержат — или отменят.
Пример

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

Ловушка
Говорить терминами — или соглашаться на всё, чтобы не спорить.
Связи
Опирается на Trade-offs, ADR и C4 Model.
§ 09

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

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

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

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

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

DecideProblem framingTrade-offsReversibilityADRweigh optionscost to undo?write it downStructureDecompositionCohesion / couplingInterface / contractMonolith → microjudge bymeet atlater splitData & runtimeSource of truthCachecopied toSync vs asyncIdempotencyretries needneeds
Три цепочки: как принимать решения, как резать систему, как жить с данными и сбоями.

Шпаргалка: все 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объяснить и сказать «нет»

Говори языком стоимости, риска и времени; умей возразить и признать ошибку.

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

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

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