Типовая ситуация: в проект приходят умные люди, менеджеры внедряют эффективные процессы, а проект все равно превращается в болото. Фичи разрабатываются месяцами, релизы откладываются, а на ретроспективах все жалуются на зависимости. При этом на схемах все выглядит красиво: микросервисы, CI/CD, облака. Что с этим миром не так?
Понятно, что «не так» может быть что угодно и как обычно it depends, но здесь и сейчас разберем одну из возможных причин, а именно ситуацию, при которой архитекторы и техлиды работают только с одним видом сложности – технологической. Рисуют квадратики, проводят стрелочки, выбирают базы данных. Реальность разработки при этом гораздо сложнее: в любом проекте одновременно живут три вида сложности, и они постоянно влияют друг на друга. Игнорируя хотя бы один из них, получим легаси с техдолгом вселенских масштабов уже через полгода (при современных условиях может и быстрее).
Определение архитектуры
Начинать принято с определений, представлю определения архитектуры, используемые в этой статье.
SA = {Elements; Form; Rationale}
Perry, Wold, «Foundations for the study of software architecture»
Последний пункт, на мой взгляд, самый важный. Рационализация – это ответ на вопрос «зачем?». Зачем нам этот компонент? Зачем такая структура? Какие риски мы снижаем или какие возможности открываем?
Основные понятия (fundamental concepts) или свойства(properties) системы в окружающей среде, воплощенной в ее элементах, отношениях, а также принципах ее проектирования и развития.
ГОСТ Р 57100-2016/ISO/IEC/IEEE 42010:2011 “Системная и программная инженерия. Описание архитектуры”
Здесь добавляется важный нюанс: не только проектирование (как структура выглядит сейчас), но и развитие (какие элементы могут появиться, как взаимодействие может измениться). Появляется динамика.
Набор ключевых решений в системе, которые избавляют разработчиков от ненужной креативн��сти.
Desmond D’Souza, Alan Cameron Wills
Это определение мне нравится тем, что заставляет задуматься :) Конечно, никто не пытается обесценить креативность. На мой взгляд это определение про понимание того, где креативность необходима, а где ее применение создает избыточную сложность.
Креативность нужна, когда:
Нет готового решения для вашей проблемы
Стандартные подходы не работают (например, в условиях highload)
Требуется нестандартный алгоритм или оптимизация
...
Цитируя Дробышевского, – когда нужно решить нестандартную задачу нестандартными способами.
Но большинство задач решаются стандартными способами. Highload начинается там, где перестают работать стандартные решения. До этой границы любую нагрузку можно поддерживать стандартными средствами.
Архитектурное знание формировалось через паттерны, – начиная с работ Кристофера Александра о проектировании городов, которые вдохновили Gang of Four на описание первых паттернов проектирования. Идея простая: для повторяющихся проблем существуют проверенные решения.
Три вида сложности
И мы переходим к сложности. Под сложностью будем понимать:
Свойство системы, характеризующееся большим количеством взаимодействующих компонентов, нелинейностью, эмерджентностью и трудностью предсказания.
Эта иллюстрация призвана продемонстрировать, что не любая ситуация суть сложная ситуация, но ненужная креативность вполне может сделать из простой ситуации сложную и непредсказуемую и вот об этом я и хочу поговорить с позиции архитектуры.
Мы разделим глобальную сложность на три отдельных части: предметную, технологическую и социальную.

Предметная (доменная) сложность
Сложность самой задачи, которую мы решаем, независимо от способа реализации. Не контролируется архитектором или разработчиком – это данность от бизнеса.
Метрики предметной сложности:
Количество доменных событий (5 или 1500)
Число доменных сущностей
Количество бизнес-сценариев
Вариативность бизнес-логики
Количество связей между сущностями
...
Например, простой внутренний бизнес-процесс может иметь несколько событий, пару сущностей, минимум правил. А банковский кредитный конвейер - сотни сущностей, сценариев, сложные правила валидации.
Лучший современный способ быстро выявить предметную область – Event Storming. Это позволяет визуализировать события, команды и политики за несколько часов интенсивной работы с доменными экспертами. Сам размер получившейся модели уже даст некоторе представление о степени сложности предметной области.
Технологическая сложность
Это то, насколько система разложима, понятна и поддерживает управляемую эволюцию. То есть то, как мы через технологии, архитектуру и структуру берем под контроль предметную сложность. Декомпозиция, модульность, способы взаимодействия компонентов, распределение кода – все это те��нологическая сложность.
Технологическая сложность прямо пропорциональна сложности предметной области и обратно пропорциональна зрелости работы с предметной областью. Чем лучше мы умеем работать с выявлением доменной сложности, тем более соответствующее техническое решение мы создадим – без переусложнения.
Практики анализа предметной области были достаточно хорошо развиты у крупных аутсорсеров (просто потому что их прибыль = оплата клиента − затраты на разработку).
Если аутсорсер переусложнит техническое решение он либо получит меньше денег, либо вообще уйдет в минус. Поэтому практики управления требованиями и архитектурного проектирования там были критически важными компетенциями.
Вне аутсорсинга эти практики реже играют фундаментальную роль, потому что компании зарабатывают на другом – на кредитах, комиссиях, подписках.
(о частных случаях предлагаю не спорить, индустрия большая и ситуации могли быть очень разными, где-то вполне могло быть плохое решение, выполненное как попало)
Социальная (организационная) сложность
Сложность, возникающая из структуры команд и необходимости их координации. Количество людей, команд, их опыт, способы коммуникации, распределенность – все это прямо влияет на скорость разработки.
Распространен маркетинговый тезис: «сделайте продуктовые, автономные, независимые команды – и будет вам счастье». Этот тезис по своей сути – миф :)
Зависимости между командами как таковой не существует. Зависимость возникает не от организационного деления, а вокруг общих ��есурсов. Если команда вносит изменения в одну и ту же систему или сильно связанные компоненты, которые не могут поставляться по отдельности, простое разделение на команды не даст независимости или автономности. Источник зависимости – это что-то вещественное: код, компонент, тестовый сценарий, база данных.
Одна компания решила повысить скорость разработки, разделив 50 разработчиков на пять продуктовых команд. Но система оставалась монолитом с сильной связанностью. Результат? Еще больше встреч, согласований и блокировок. В основе проблема была в архитектуре, а не в структуре команд.
Закон управления сложностью
Все три типа сложности взаимосвязаны. Плохое решение в одном измерении порождает проблемы сразу во всех трех.

Золотые правила:
Всегда смотрите на все три измерения одновременно
Не оптимизируйте одно измерение за счет других
Часто причина видимой проблемы в одном измерении лежит в другом
Если у вас в коде то самое спагетти, можно хоть всю жизнь по-разному перегруппировывать команды, запускать Scrum, Kanban – ничего не изменится. Проблема в другом месте (спойлер: в архитектуре/в коде).
Наиболее частые ошибки возникают из-за несоответствия типов сложности.
Высокая предметная сложность + неуправляемая технологическая
Сложный финтех-домен + монолит без разделения на модули. Все смешано в одной кодовой базе без четких границ, очень сложно разобраться, где бизнес-логика, где инфраструктура, где обработка данныхПростой домен + гипервысокая технологическая сложность
Todo List + микросервисы + Event Bus + Saga. Классический оверинжиниринг. Для простого CRUD-приложения не нужна распределенная система с eventual consistency и сагами. Это создает огромные накладные расходы на разработку, тестирование, мониторинг при нулевой выгоде.Управляемая технологическая + высокая социальная сложность
Чистая архитектура + 50 человек в команде. Каждый день встречи, согласования, никто ничего не делает, velocity = 0. Идеальная архитектура не спасет от коллапса коммуникаций в огромной команде.Управляемая архитектурная сложность + неуправляемая сложность кода
Редкое, но возможное сочетание. Компоненты выделены правильно, но внутри функции с цикломатической сложностью >20 и прочие code smells. Изменения занимают по 10 недель, потому что код настолько сложный, что в нем невозможно разобраться. Архитектура бессмысленна без воплощения. Сложность кода тоже должна быть под контролем.
Управление сложностью
Архитектура нужна для управления сложностью и большинство IT-проектов находятся в комплексной (complex) ситуации, а не просто сложной (complicated):
Complicated (сложная, упорядоченная): есть причинно-следственные связи, можно аналитически предсказать последствия решений.
Complex (комплексная, неупорядоченная): нельзя точно предсказать влияние решения. Меняем маленький компонент — через инфраструктуру это влияет на совершенно другую команду, у которой падает выручка.

В комплексных ситуациях мы работаем итеративно: выполняем действие, смотрим на результат (обратную связь), корректируем дальнейший путь. И наши технологические решения не живут в изоляции, чтобы они работали долго и приносили пользу, они должны по уровню сложности соотносится со сложности предметной области, под которую проектируются и в согласии с социальной сложностью системы, воплощающей архитектурное решение.
Заключение
К какой мысли я хотел подвести этой статьей? Мысль очень простая в своей формулировке и сложная в воплощении: архитектура дает базу для управления всеми тремя видами сложности. Да, на доменную она не влияет напрямую, но может либо открывать новые возможности, либо препятствовать развитию. Социальная, видимая, сложность живет в плотной связке с технологической, – структура команд, способы коммуникации, компетенции, – все это связано прочной нитью с тем, какие инженерные и архитектурные решения мы принимаем и иногда, когда компания стремится к «снижению time-to-market» именно архитектор и архитектура могут оказаться первыми и главными помощниками.
Иногда архитектор, рисуя диаграммы уходит в роль художника, в такие моменты очень полезно остановиться на секунду и задать себе вопрос: зачем нужен этот компонент, какую сложность он снижает или какую возможность открывает, какую сложность (предметную, технологическую, социальную) он добавляет?
За каждым квадратиком стоят люди, время и деньги. Рационализация из определения в самом начале – это не формальность, а ответственность архитектора перед командой и бизнесом.
