Привет! Меня зовут Данил, я фронтенд-разработчик в компании МойСклад. В начале этого года я понял, что мне нужна задача, которая качественно прокачает мои навыки, задача с совсем другим уровнем сложности и ответственности. И мне повезло. Именно в этот момент понадобилось разработать новую архитектуру для целого домена интеграций с внешними площадками онлайн-торговли.
Когда задача была согласована с руководителями, я вдруг осознал, что моё желание решить большую архитектурную задачу и умение это делать — совершенно разные вещи. Я был в растерянности. Не понимал, с чего начать, куда двигаться и какие у меня вообще есть варианты.
Необходимая вводная часть
Основная сущность в моей задаче — коннектор. Это отдельная интеграция между МоимСкладом и конкретной площадкой онлайн-торговли. Коннектор Ozon, коннектор Wildberries и так далее.
На момент старта задачи существовал только один такой коннектор, пробный, Shopify. А всего их ожидалось минимум двадцать, и у каждого свои особенности.
Откуда взялась тревога?
Пугал масштаб последствий. Было понятно, что архитектура закладывается на годы вперёд, и цена ошибки на старте будет расти вместе с числом подключённых коннекторов.
У меня был всего один реализованный коннектор, Shopify, а рассуждать нужно было сразу про двадцать. Проблема была в объёме информации, в необходимости удержать в голове десятки нюансов сразу и понять, как среди множества деталей будущих коннекторов отличить те, что реально повлияют на архитектуру, от частностей, которые можно оставить на потом.
Ну и банально, я не понимал, с какой стороны подступиться и какие вообще бывают архитектурные решения для подобных случаев.
Что такое ADR?
По сути, ADR (Architecture Decision Record) — это короткий документ, который фиксирует одно архитектурное решение вместе с причиной, по которой его приняли, рассмотренными альтернативами и последствиями, к которым решение приводит. Идею предложил Майкл Найгард в блог-посте 2011 года "Documenting Architecture Decisions", и с тех пор подход разошёлся по индустрии. Сейчас его шаблонами и практиками применения занимается открытое сообщество на GitHub.
У нас в компании этот подход уже был в ходу, я видел, как другие разработчики оформляют такие документы для своих задач, и примерно понимал формат. Поэтому решил попробовать применить его сам, а не изобретать велосипед.
Основа для ADR
Важно сразу сказать, что ADR не жёсткая методология с обязательным протоколом, а скорее взгляд на задачу. У него есть несколько более-менее постоянных разделов, но конкретная форма и глубина проработки каждый раз собираются заново, а не берутся из единого стандарта.
Поэтому прежде чем перейти к вариантам архитектуры, мне понадобилось создать основу, опираясь на которую я мог бы размышлять. Для меня это вылилось в два отдельных этапа.
Сначала я начал документировать текущее состояние кодовой базы. Важно было описывать это честно и по пути фиксировать замеченные проблемы в существующей реализации. Уже реализованный коннектор Shopify тут оказался очень кстати.
Когда я закончил этот материал, то понял, что ключевой вопрос, стоящий перед новой архитектурой, на самом деле состоял из двух частей. Где проходит граница между тем, что должно быть общим для всех будущих коннекторов, а что останется особенностью конкретной интеграции. И как это разделение физически выражается внутри модуля, в отображении интерфейса, обращении к API и хранении состояния.
Тогда я подробно проанализировал именно этот момент, и получился документ "Анализ границы ответственности текущего состояния".
После того как я закончил работать с этой основой, в голове появилось достаточно понимания и структурированности относительно объёмов, границ и нюансов стоящей передо мной задачи.
Структура ADR
У классического шаблона Найгарда всего пять разделов: заголовок, статус, контекст, само решение и его последствия. С тех пор появились и другие форматы, например MADR, более подробный и структурированный, или Y-Statements, наоборот, максимально сжатая запись решения буквально в одно предложение. Полный список того, что использует индустрия, можно найти в каталоге шаблонов сообщества adr на GitHub.
Я в итоге не следовал ни одному шаблону дословно.
Структура моего ADR получилась такой:
Контекст модуля
Архитектурные задачи
Фокус текущего ADR
Критерии успешности
Family как архитектурная сущность
Варианты архитектурных решений
Вариант 1. Подключение на уровне коннектора
Вариант 2. Подключение через family и коннектор
Вариант 3. Подключение через универсальную connector-specific сущность
Сравнение вариантов
Вывод по сравнению
Принятое решение и дальнейшие шаги
Так как я предлагаю смотреть на ADR не только как на инструмент для решения прикладных задач, но и как на способ снизить тревогу перед большой задачей, то и структуру документа я бы предложил выбирать с таким уровнем детализации, при котором лично вам становится спокойнее и увереннее при принятии решения.
Я не буду разбирать тут каждый раздел подробно, хочу лишь подсветить несколько тонких моментов, которые лично мне показались особенно важными и неочевидными.
Варианты, а не витрина
ADR предполагает несколько путей решения задачи, из которых потом обоснованно выбирается один. Это может подтолкнуть того, кто составляет документ, взять вариант, который субъективно кажется самым удачным, и подобрать под него пару заведомо проигрывающих альтернатив. Документ при этом получается логичным и красивым, но напрочь теряет смысл.
Я сам столкнулся с этой проблемой. Было непросто найти именно конкурентоспособные варианты, которые решали бы задачу с близкой эффективностью, а отличались скорее идеологически и концептуально. Поэтому я прошёл несколько кругов, каждый раз пересматривая варианты и вычеркивая те, что по ходу анализа показывали явную несостоятельность.
Решение рождается не в ADR
Второй важный момент, ADR это не источник решения, а всего лишь инструмент, который помогает его принять. Например, в своём документе я завёл отдельный раздел "Сравнение вариантов", приведу его целиком:

На первый взгляд кажется, что эта таблица уже дает все основания выбрать вариант, набравший больше всего баллов. Но такой выбор оказался бы чисто формальным. Таблица здесь не источник итогового решения, а лишь основа для дискуссии. После того как я составил эту часть, мы созвонились с архитектором фронтенда компании, главой гильдии фронтенда и несколькими ведущими разработчиками, и настоящее решение родилось уже в разговоре, для которого этот документ послужил отправной точкой. Показательно, что вопреки результатам таблицы выбрали Вариант 1, хотя по баллам он занял только второе место.
Что делать после ADR?
Формально на предыдущем разделе я мог бы закончить статью, но прожитый опыт показывает, что в реальности процесс принятия архитектурного решения на этом не заканчивается. ADR продолжает участвовать ещё в нескольких этапах.
Реализация выбранного решения
После того как мы с коллегами обсудили и приняли решение, стало понятно, что впереди ещё несколько этапов, которые тоже требуют фиксации:
первый этап реализации
повторное ревью
подтверждение или опровержение выбранного решения
выход на поддержку
ADR — это не приговор
После того как решение выбрано, это не значит, что оно идеальное и не может оказаться неверным. ADR лишь повышает осведомленность перед принятием решения. Поэтому для нас было важно проверить адекватность принятой архитектуры на практике. Мы выбрали понятный, логически цельный и достаточно объёмный кусок реализации, на котором можно было бы опробовать архитектуру, а после встретились еще раз, чтобы критически оценить результат и при необходимости скорректировать решение.
Жизнь после ADR
Вот я оказался в точке, где проанализировал всю нужную базу для составления ADR, составил его, в дискуссиях и обсуждениях принял решение на его основе и даже проверил решение на практике, частично внедрив архитектуру и проведя повторное ревью.
Важно понимать, что ADR — не документация, которая требует постоянной поддержки, хотя корпоративные реалии могут незаметно привести именно к этому. У ADR есть конкретная цель, и когда она выполнена, документ остается артефактом, к которому можно будет обратиться в будущем, но перестаёт быть документацией, описывающей актуальную архитектуру.
Если у вас в компании есть похожие процессы и нужно поддерживать актуальную документацию решения, для этого должен быть отдельный документ, а не сам ADR. Например, после того как решение было принято, я отдельно зафиксировал текущую архитектуру как факт, без деталей о том, почему выбрали именно её, в документе "Как добавить новый коннектор". Внутри него есть ссылка на исходный ADR, но источником истины теперь служит именно этот новый документ.
Вместо итогов
Сейчас, когда весь этот путь уже пройден и отрефлексирован, он кажется понятным, правильным и логичным. Но в процессе ощущения были совсем другие. Я часто не понимал, какой этап делать следующим, и структура моего ADR в итоге родилась не из плана, а из одного и того же вопроса, который я снова и снова задавал себе: "Достаточно ли я сейчас знаю, чтобы идти дальше?" Если ответ был "нет", я пытался понять, чего именно не хватает.
Я надеюсь, что этот текст поможет тому, кто впервые столкнется с похожей задачей, пройти её немного легче и чувствовать себя не так растерянно, как чувствовал себя я.
Да, я не архитектор с опытом построения десятков высоконагруженных и масштабируемых систем с нуля. Но у каждого архитектора с таким опытом когда-то была его первая архитектурная задача.
Ссылки:
Michael Nygard, Documenting Architecture Decisions — оригинальный пост 2011 года, с которого началась практика ADR
Architectural Decision Records — обзорная страница открытого сообщества, поддерживающего практику ADR
Каталог шаблонов ADR — сравнение форматов, включая Nygard, MADR и Y-Statements
Olaf Zimmermann, MADR Template Primer — подробнее про формат MADR
Y-Statements — короткая запись архитектурного решения в одно предложение

