Отказоустойчивый и масштабируемый энтерпрайз невозможно спроектировать по книжкам. Одно и то же решение может фигурировать и в best, и в bad practice — и, что забавно, иногда переходит из одного списка в другой. Ещё недавно монолиты считались злом, а теперь снова в моде.

Хотите посмотреть, как знакомые паттерны ведут себя в реальном контексте?

В CDEK за двадцать пять лет работы накопился богатый арсенал архитектурных решений — удачных, спорных и по-своему эффективных. Делали костыли? Конечно. Изобретали велосипеды? Возможно, лучшие в стране. А бывало и наоборот: думали, что жертвуем архитектурой ради дедлайна, а в итоге получалось решение, которое живёт годами.

На связи Наталья Макарова, техлид внутригородской логистики и глава Гильдии Java. По работе я либо проектирую архитектурные решения, либо выбираю из предложений команды те, что реально двигают бизнес.

За годы техлидства я убедилась: идеальных архитектурных паттернов не бывает. Один и тот же подход в разных условиях может стать и спасением, и катастрофой. Всё решает контекст.

Чтобы показать это на практике, я собрала три инженерных кейса. Каждый оформлен в формате детективного квиза: роль, фабула, вопросы на размышление, разбор и выводы. Попробуйте разобраться в проблеме, пройти тест и определить: где костыль, где инженерный компромисс, а где — настоящая best practice.

Содержание:

Кейс 1. Дело о поисках утраченного времени

Вы — сеньор-разработчик, не первый год работаете в компании. Исторически ваши модули и данные жили в новосибирском ЦОДе. Но бизнес вырос, мощностей перестало хватать и расширить их нельзя. Поэтому функционал переезжает в московский ЦОД.

Вы прошли чек-лист миграции: упаковали сервис в Kubernetes (старые модули местами ещё не в нём, но при переезде это обязательный шаг) и перевезли функционал в московский ЦОД. На старте всё выглядело штатно — пользователи не жаловались, метрики в зелёной зоне.

На следующее утро посыпались алерты: API отвечает дольше нормы. Причина непонятна — это время, нетипичное для пиковой нагрузки, поэтому начали копать.

Расследование показало: в CDEK было принято запускать технические шедулеры  утром по Новосибирску. Они «убирали» данные, подбивали статистику и резали партиции. Так было удобно, потому что в 6:00 в Москве низкая нагрузка, а если что-то шло не так — команда была уже на месте.

Но шедулер «проснулся» по московскому времени в 10:00 и добавил нагрузку в разгар трафика.

Причина банальна: расписания привязаны ко времени сервера. Но сервер переехал из Новосибирска в Москву, и сменился часовой пояс.

Возник вопрос: что с этим делать? Понятно, что зависеть от времени сервера — это пережитки старых времен, и даже тогда это было моветоном. Переписать бы... Но это же не одна такая команда, за годы жизни CDEK успело накопиться легаси. Если делать по-правильному, придётся месяцев на 8−9, а то и на год сдвигать переезд в московский ЦОД, а у нас нет на это ресурса.

Решение приняли прагматичное: на уровне инфраструктуры зафиксировали часовые пояса для конкретных компонентов — какие механизмы, сервера и базы «живут» в каком времени. Исторически «сибирские» модули оставили в новосибирском времени.

Контрольные вопросы

Вопрос 1. Костыль ли — менять системное время сервера по запросу разработки?

А. О, да.
Б. Нет, это хорошее гибкое решение.

Скрытый текст

Правильный ответ: да, это костыль. Идеал — переписать. Другой вопрос, что на это совсем нет времени.

Вопрос 2. Почему не переписали сразу?

А. Недостаточная мотивация разработчиков.
Б. Принятое решение лучше.
В. Ограниченность времени на переезд.

Скрытый текст

Ответ В — жёсткое ограничение по срокам миграции, а не «лень разработчиков» или «любовь к костылям».

Чек-лист: когда костыль оправдан

Перейдём от кейса к рекомендациям. Что нужно помнить, если вы решаете похожую задачу:

  1. Ожидание «правильного» решения убивает бизнес. В нашем кейсе годовая задержка переезда в московский ЦОД грозила остановкой: хранить данные было негде. Важно не путать этот пункт с ситуацией, когда можно спокойно сделать правильно с первого раза, но просто хочется выпуститься быстрее под давлением менеджеров. Там, может быть, есть смысл сразу сделать хорошо.

  2. Костыль в разы дешевле полноценного решения. Если доработка по трудозатратам сопоставима с нормальным рефакторингом, смысла нет.

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

  4. Костыль не мешает делать правильно. Это про ситуацию, когда чтобы начать внедрять правильные решения, надо сначала убрать костыли. Это «уловка 22» — безвыходная ситуация, в которой попытка соблюсти одно правило приводит к нарушению другого. Из этой истории невозможно выйти, костыль останется с вами навсегда.

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

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

Кейс 2. Дело о непрозрачных подсказках

На этот раз вы — solution-архитектор.

На планёрке архитекторов CTO просит вас разобраться с проблемой одной из команд: они никак не выпустят функционал, который нужен всем витринам компании. Сроки срываются, а задача для бизнеса приоритетная.

«Ты же архитектор, сходи, узнай, что у них там тормозит».

Вы начинаете расследование. Документации, как водится, никто не писал — обещают «потом как-нибудь оформить». Вы этому не верите: сами не раз так делали. Из обрывков бесед с командой выясняется, что речь идёт об обычном автокомплите адресов: ввёл «М» — получил Москву, дальше улицу и т.д. В целом задача не выглядит сложной и непонятно, почему работа стоит.

Смотрите их заявку на архсовет — внутренний совет архитекторов, куда приходят за одобрением нового микросервиса. Архитектурная схема тоже в комплекте — всё как положено:

По заявке команда собиралась сделать два бэкенда и пришла за утверждением архитектуры:

  • Интегратор (address-hints-integrator), который собирает данные из шины и хранилищ, объединяет и кладёт в нереляционную БД (в нашем случае — Elastic).

  • Модуль подсказок адреса (address-hints), который обрабатывает пользовательские запросы и обращается к Elastic.

Архитектура выглядит нормально, ничего сверхъестественного: команда уже не раз делала похожие вещи. Проблема явно не в архитектуре.

Возникает закономерный вопрос: а не проще ли купить готовый автокомплит? На рынке таких сервисов достаточно — и в любом случае закупка шла бы через тендер. Но у сторонних решений есть нюанс: наиболее точные — как правило, самые дорогие.

Но ребята объясняют: всё не так просто. Подсказки должны быть обогащены внутренней CDEK-информацией — расстоянием до ближайшего ПВЗ, «логистическим городом» и другими служебными параметрами. Если брать сторонний сервис, поверх него всё равно придётся строить собственное API для обогащения данных. Это займёт время и выведет проект за рамки нефункциональных требований. Решаете, что писать самим всё же есть смысл.

Идёте дальше — может, дело в процессах разработки? Смотрите трекер: задачи декомпозированы, эпики заведены, вроде, всё нормально… Но вдруг взгляд цепляется за строку: «кэш подсказок — 140 часов»!

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

— Почему задача висит?
— В этом шарит только Вася, он в отпуске.
— А что за бас-фактор на Васе? Почему другой не может подхватить?
— Понимаешь, тут особая история. Мы решили сделать на реактивном подходе. С этим почти никто не работал, один Вася и знает, как. Остальные могут что-то подправить по мелочи. Вася сделал кэш и ушёл. На тестировании нашли баг, выделили два дня на исправление, не исправили и решили переключиться на другие задачи. Иначе можно неделю копаться и просто потерять время.

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

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

 

В нашем случае пайплайн выглядел примерно так: пользователь отправляет запрос — «Найди-ка мне адреса на букву М». Один поток спрашивает: «Кто возьмёт поиск в кэше?» — находится желающий, получает задачу и начинает обрабатывать. Первый поток в это время освобождается и должен переходить к следующему запросу.

На практике всё пошло иначе. Пока второй поток занимался кэшем, первый почему-то ждал завершения задачи, вместо того чтобы освободиться. В результате приложение потеряло реактивность: операции снова выполнялись последовательно, как в старом добром синхронном мире.

А на самом деле всё оказалось ещё интереснее. Перед обращением к кэшу запрос идёт в модуль аутентификации/авторизации. И там один поток ждёт, пока другой завершит работу, то есть зависает в статусе waiting:

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

И тут начинается любопытное: модуль авторизации работает по синхронному REST, потому что реактивность в CDEK пока не везде прижилась. Сделать его совместимым с реактивными потоками можно, но ради одной команды переписывать никто не будет — у всех свой бэклог и приоритеты. В итоге внутри реактивного пайплайна возникает синхронный вызов, блокирующий поток.

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

Вот как всё выглядит на идеальной схеме:

  1. Поток из реактивного пула передаёт задачу в пул синхронных потоков.

  2. Синхронный поток авторизует пользователя и возвращает результат.

3.

Управление возвращается в реактивный пул, который продолжает работу — поиск в кэше, обращение к Elastic, обновление данных и т.д.

А теперь к тому, что получилось в реальности. Синхронный поток действительно отработал проверку пользователя, но не вернул управление обратно в реактивный пул. Вместо этого он пошёл выполнять остальное: поиск в кэше, запрос к Elastic, обновление индекса — и только спустя долгое время вернулся с сообщением «всё готово, возвращаю в пул реактивных потоков».

Фактически вся работа выполнялась синхронно, а реактивность исчезла.

Но ребятам ещё больше не повезло: пул реактивных потоков случайно совпал с дефолтным пулом для работы с БД. По умолчанию это 10 потоков на ядро — у нас получилось 40 и там, и там. В итоге все они блокировали друг друга, система вставала колом, а разработчики не понимали, где искать причину.

Исправить это можно одной строкой кода. Но дело было не в объёме работ, а в том, чтобы понять, где именно искать.

Если коротко, всё упёрлось в реактивность, которой не случилось. Что имеем в результате расследования:

  1. Синхронный вызов модуля авторизации внутри реактивного пайплайна — это данность, «не лечится».

  2. Вынести такие вызовы в отдельный пул синхронных потоков — решение правильное, и команда так и сделала.

  3. Но дальше промах: поток не вернул управление обратно в реактивный пул. Java этого автоматически не делает, поэтому нужно добавить одну строчку кода, чтобы вернуть управление.

  4. Дополнительная ловушка — дефолтное число реактивных потоков совпало с пулом потоков БД. Всё заблокировалось, и приложение встало колом.

Исправляется всё это буквально в пару строк, если знать, где копать. Но именно в этом и кроется боль архитектора: когда решение быстрое, но команда не знает, где искать, и не понятно, что им посоветовать.

Контрольные вопросы

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

Вопрос 1. Обоснованно ли команда выбрала реактивный подход?

А. Да, перспективный подход для таких задач.

Б. Нет, эта технология вообще не про это.

Скрытый текст

Правильный ответ — обоснованно. Реактивный подход как раз и придуман для таких сценариев: когда есть много пользовательских запросов, каждый состоит из нескольких последовательных шагов, но обработка должна быть быстрой, без ветвления логики и с контролем нагрузки. Реактивность тут прямо то, что доктор прописал. Другой вопрос, что ребята не смогли её приготовить.

Вопрос 2. Главный фактор неудачи команды?

А. Отсутствие документации.

Б. Нет ресурса на обучение.

В. Неправильная декомпозиция.

Г. Недостаточная мотивация.

Скрытый текст

Ответ — Б, нет ресурса на обучение. Вася — единственный, кто понимал реактивность, ушёл в отпуск, и всё встало. Документация, конечно, помогает, но не она решает дефицит экспертизы. Проблем декомпозиции не замечено, как и проблем с мотивацией команды. Просто некому больше было подхватить стек.

Вопрос 3. Какое действие архитектора будет самым эффективным с точки зрения бизнес-фокуса компании?

А. Не дожидаясь Васи из отпуска, переписать проект на обычный стек.

Б. Не дожидаясь Васи, самому доделать задачу с кэшем.

В. Срочно начать обучать команду реактивному стеку.

Скрытый текст

Ответ — А, переписать на обычный стек.

Сейчас бизнес ждёт релиз, а не мастер-класс по реактивности. Реактивный стек — правильное решение, но не в этом контексте: команда не готова и не умеет, инфраструктура его не поддерживает, сроки горят.

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

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

Вопрос 4. Правильно ли команда переключилась на другие задачи после двух дней безуспешных попыток исправить баг?

А. Да.

Б. Нет, нужно было продолжать попытки решить задачу.

Скрытый текст

Ответ — А, правильно.

Баг нашли на этапе тестирования — пользователям он не мешал.  Команда переключилась на другие задачи, и в этих условиях это было правильное решение. Если бы ошибка влияла на пользователей, история была бы другой: тогда нужно чинить, пока не починишь, без сна и жалости. Но здесь — не тот случай. Есть известное правило из тайм-менеджмента: если не понимаешь, как решить задачу, задай себе лимит времени на исследование. Потратил этот лимит — оцени ситуацию. Если продвижения нет, значит, нужно либо переформулировать задачу, либо обратиться к более опытным коллегам, либо отложить до лучших времён.

Чек-лист: когда от технологии не стыдно отказаться

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

  1. Нехватка опыта команды. И под командой мы понимаем не только проектную, а всю инженерную экосистему. В этом кейсе — команда всего CDEK. Потому что если с новой технологией возникает баг, а в чате разработки никто не подскажет, как его исправить — вы одни в поле. Это повод отложить эксперименты.

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

  3. Проблемы с интеграцией. Например, если соседние сервисы и фронт живут на синхронном стеке, то взаимодействие с нашими реактивными экспериментами будет требовать дополнительных «приседаний».

  4. Сложность архитектуры. Почти все новые паттерны решают узкие, специфичные задачи, часто с большим объёмом данных, и за это всегда приходится платить усложнением. Не каждая система в этом нуждается.

  5. Сложности с тестированием. Если технологию невозможно полноценно протестировать, это тоже показатель, что она нам не подходит. Потому что новая технология не стоит риска уменьшить надёжность системы.

Кейс 3. Дело о неразлучных близнецах

Теперь представьте, что вы джун-девопс и работаете первую неделю.

На общем собрании вам объяснили задачу: «Мы переезжаем в московский ЦОД. Это растянется на несколько месяцев, в основном это задачи для инфраструктурщиков — то есть для вас. Вот список из 100-500 пунктов. Главная задача для вас, девОпсов команд, — экономить ресурсы: чистить старые экспериментальные базы, тестовые окружения и прочие «дай 20 гигов, кое-что попробую». Вы киваете: «Понял».

Идёте изучать ресурсы ваших подопечных команд и натыкаетесь на странность: в Elastic лежат два индекса — один от 10 апреля, второй от 15-го. Подсказки адресов, наш старый знакомый модуль. Кажется, всё ясно — кто-то просто забыл удалить старый индекс. Что делать? Удалить, сэкономить место, всё логично.

К счастью, прежде чем нажать Enter, вы, как настоящий девопс, делаете бэкап. И правильно — инстинкты спасают карму.

Почти сразу после удаления модуль начинает «пятисотить», всё рушится. Вы быстро понимаете, что произошло, откатываетесь из бэкапа — и система оживает. Алерты сработали, но буквально на пару секунд. Никто ничего не заметил.

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

Сразу удалять базы вы на всю жизнь разучились, поэтому пошли смотреть в конфиги — действительно, два индекса:

write-index: hints_15-апр 

read-index: hints_10-апр

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

На этот раз вы решили не спешить и сходили к разработчику модуля. Тот, к сожалению, только пожал плечами: 

— Техлид зачем-то так сделал, но его сейчас нет  (с ними так всегда — когда особенно нужны, они либо на конференции, либо в отпуске). Давай гляну код.

Разработчик изучил код и подтвердил:

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

— А зачем так?

— Ну, пользователи работают с одним индексом, а во втором мы исправляем опечатки и ошибки. И когда накопим исправлений за неделю, в один момент переключаем пользователей на этот новый вариант индекса. Давай пока ничего не будем удалять, но переключим оба индекса на старый. Мы же точно знаем, что старый отключать нельзя.

Кстати, вот как это устроено в коде: есть индекс, куда смотрят запросы от пользователей (10 апреля). Есть индекс, который под администрированием (15 апреля): в нём исправляются ошибки в адресах и т.п. И раз в неделю происходит процедура переключения: создаётся третий индекс (20 апреля), на него переводятся задачи администрирования. Индекс, который был под администрированием раньше, становится индексом для обработки запросов пользователя. А старый индекс для пользователей удаляется.

Разработчик смеётся:

— Похоже на оверинжиниринг, правда? Техлид приедет, я ему покажу, что нашёл. (Какой стрессоустойчивый техлид! - Прим. автора)

Вместе вы решили удалить лишний индекс — почему бы и нет. Всё переключили, проверили — ошибки начали исправляться быстрее. Воодушевлённые, удалили новый индекс, тот самый за 15-е апреля, а не за 10-е число.

Сначала всё выглядело нормально и ничего не «пятисотило». Но ночью по Москве техлида всё же подняли из отпуска — просто во Владивостоке уже утро. Пользователи проснулись, пошла нагрузка, и внезапно начали дико тормозить подсказки.

Скрытый текст

Забегая вперёд: это был день, когда решили переименовать Астану в Нур-Султан. Город, который менял название дважды за короткий срок, стал причиной локальной катастрофы.

Техлид зашёл,  увидел манипуляции с индексами и быстро вернул конфигурацию обратно. А потом оставил лаконичное сообщение: «Я для кого ADR (Architecture Decision Record) пишу? Почему их никто не читает? Прочитайте. Приеду, устрою вам тестик».

ADR (Architecture Decision Record) — это запись архитектурного решения.

Давайте и мы заглянем в этот тестик от техлида.

Контрольные вопросы

Вопрос 1. В каком случае нужна нереляционная БД?
Это теоретический вопрос. Техлид проверяет, помнят ли ребята теорию.

А. Когда нужна строгая целостность данных.

Б. Когда важна высокая скорость транзакций.

В. Когда нужно обрабатывать большие объёмы неструктурированных данных.

Скрытый текст

Ответ — В. Первые два пункта как раз про реляционные базы: они обеспечивают целостность и быстрые транзакции. В NoSQL про транзакции речи вообще не идёт.

Вопрос 2. За счёт чего нереляционные БД хорошо работают с полнотекстовым поиском?

А. Встроенные механизмы связи между частями индекса.

Б. Инвертированный индекс.

В. Сложные оптимизированные запросы выборки.

Скрытый текст

Ответ — Б, инвертированный индекс. В этом и заключается волшебство: именно инвертированный индекс позволяет искать слова и фразы мгновенно. Остальное здесь вторично.

Вопрос 3. Почему поиск стал тормозить?

А. Операция записи ненадолго блокирует операции чтения, аналогично многим базам данных.
Б. Сбросился кэш.
В. Операция записи триггерит массовые изменения в инвертированном индексе.

Скрытый текст

Правильный ответ — В. При обновлении данных в инвертированном индексе приходится линейно менять все связанные документы — например, если город Астана переименовали в Нур-Султан, нужно пройтись по всем записям, где это слово встречается. Процесс долгий, и пока он идёт, всё тормозит.

Вопрос 4. Было ли решение использовать два индекса — на чтение и запись — костылём?

А. Всегда да. Нереляционные БД созданы для быстроты поиска.

Б. В данном случае да, так как изменения вряд ли были масштабными.

В. Нет, это архитектурный шаблон.

Скрытый текст

Ответ — В, это не костыль, а корректный архитектурный шаблон.

Давайте объясню. В нереляционной БД операция обновления происходит так: приходит запрос, выбираются все документы, где участвует изменяемый элемент адреса. Дальше в них линейно обновляются токены и записываются обратно. Процесс тяжёлый, особенно если меняется что-то верхнеуровневое — например, название города. Например, опять переименовали Астану. То есть придётся переписать каждый адрес этого города.

Чтобы система не вставала колом, используется шаблон Read/Write Separation — разделение чтения и записи.

Мы с ним хорошо знакомы. Операция записи — только к мастеру, а считываем — только с сейвов для реляционных БД, или вьюхи для статистики — работают по тому же принципу. В Elastic этот подход реализован через два индекса: один на чтение, второй на запись. Может, это и усложняет архитектуру, но иногда по-другому никак.

Чек-лист: вопросы, на которые отвечает ADR

И по заведённой схеме, чек-лист по ADR, потому что если бы наши герои вспомнили про него и что в нём за информация, всего бы этого не случилось.

ADR (Architecture Decision Record) — это не формальный документ, а способ зафиксировать, почему именно так решили реализовать. Он помогает помнить контекст, альтернативы и последствия решений. Хороший ADR должен отвечать на несколько базовых вопросов:

  1. Когда мы это решили? Не надейтесь, что вспомните через два-три года. В моменте кажется, что обстоятельства в памяти навсегда, но всё забывается.

  2. Почему в коде не так, как написано в ADR? Часто ADR устаревает: решение пересмотрели, код изменили. Это нормально. Главное — зафиксировать статус: «ADR был принят, потом отменён». Никогда не удаляйте старые ADR — они могут пригодиться, если ситуация повторится.

  3. О чём мы думали? Это вопрос про контекст — что влияло на выбор. В нашем случае это был переезд в московский ЦОД. Контекст ограничивает и объясняет, почему именно такое решение было единственно реалистичным.

  4. Почему мы не сделали по-другому? ADR должен перечислять альтернативы. Я всегда прошу ребят проработать минимум два варианта. В ответ иногда слышу: «Нет других, только так можно!» — но альтернативы есть всегда.

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

Мораль

Главная мысль, которой хочу поделиться: не стоит идеализировать архитектурные паттерны. Ни один подход не идеален и работает только в своём контексте.

Оскар Уайльд на эту тему даже целый роман написал: хочешь быть всегда совершенством, превратишься в чудовище.

А если коротко, моя мораль в трёх пунктах:

  1. Костыль — это нормально, но если им лечить перелом, а не простуду. Главное — применять его в нужный момент.

  2. Новое — это лучшее, но часто — враг хорошего. Не бойтесь отказываться от новой технологии, к которой вы не готовы.

  3. Приняли решение — зафиксируйте его в ADR. Память короткая, а архитектурная история должна храниться не только в голове у техлида.

Поделитесь в комментариях вашими кейсами, когда костыль был оправданным решением!

Скрытый текст

А чтобы быть в курсе последних тенденций отрасли и узнавать обо всём из первых уст, следите за обновлениями на сайте HighLoad! В следующем году на конференции вас ждёт масса всего интересного!

Комментарии (16)


  1. iv_kingmaker
    22.12.2025 09:00

    Статье всего час, 0 комментариев, 24 лайка и 24 закладки, меньше 3k просмотров, интересно. В дополнение, посредственная информация, перепаханная LLM.


    1. funca
      22.12.2025 09:00

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


  1. Fedorkov
    22.12.2025 09:00

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

    Но ведь Вася к тому времени уже вернётся из отпуска.


    1. nmakarova Автор
      22.12.2025 09:00

      Да, но он может быть еще много где, кроме работы) На конференции/ на больничном/опять в отпуске/ в декрете/уволиться... И даже просто занят другой такой же важной задачей. В любом случае, ненадежно, если только один может в коде разобраться.


      1. Fedorkov
        22.12.2025 09:00

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

        Другое дело — если Вася хронически перегружен работой, либо другие члены команды не дотягивают по уровню; но из статьи этого не видно.


        1. svz
          22.12.2025 09:00

          Справедливости ради, неизвестно насколько сам Вася хорошо понимает реактивную механику и сколько ещё ошибок допустит в процессе.


    1. AdrianoVisoccini
      22.12.2025 09:00

      возвращаешься из оипуска - на хабре осуждают как из-за тебя фича зависла на бекею

      Вась, не стрессуй, это не твоя вина.


      1. nmakarova Автор
        22.12.2025 09:00

        ))) От Васи получено разрешение


  1. svz
    22.12.2025 09:00

    Видел эти примеры на одном из докладов ) Про часовые пояса конечно было странно слышать, но в целом - жизненно.


    1. nmakarova Автор
      22.12.2025 09:00

      Спасибо! Про часовые пояса: у нас была дискуссия выносить ли это в паблик) В итоге решили, что раз уж про реальный опыт, а мы ну правда же потратили на это довольно много времени, то нечего скрывать.


  1. Grikhan
    22.12.2025 09:00

    Правильный путь, направленье не то. Делать вывод, что костыли не только вредны, но и полезны на основании того, что в условиях невыплаченного техдолга с косячным шедулером нет других вариантов, кроме дальнейшего накостыливания и того, что архитектор незнаком со своим фреймворком и аппрувит незнакомые никому, кроме, может быть (но это не точно) Васи, решения (см.TOGAF фазу Е), из-за чего крит висит две недели и надо-таки сделать как надо было сразу – ну так себе.

    Оправдывать свои ошибки вместо работы над ними – это путь к деградации.


    1. nmakarova Автор
      22.12.2025 09:00

      Возможно. А как было бы правильно? (Я если что правда интересуюсь)


  1. oldDBA
    22.12.2025 09:00

    Лет двадцать назад от одного очень уважаемого Архитектора из очень большой компании получил наиболее точное определение позиции EA - Compromise maker. И есть еще старая байка про "Барин, в каком стиле дом строить?". Накостылять в ландшафте - да как... А вот построить правильное управление техдолгом и развитием, не вредя бизнесу и разработке - искусство, а фреймворки и паттерны - инструменты и расходники, и их выбирают в зависимости от.


  1. woodginn
    22.12.2025 09:00

    Зачем в этой истории архитектор - то?


    1. nmakarova Автор
      22.12.2025 09:00

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


  1. onets
    22.12.2025 09:00

    Я не пойму это выдуманные истории?

    Сдек работает на всю страну, клиенты и пункты выдачи по всей стране в разных часовых поясах. И вы не сталкивались с проблемами часовых поясов? И не знали что сервера и всякие логи должны быть в utc?

    И что за синхронный REST? Синхронная авторизация? Что это значит? В Java веб сервера работают в один поток??