
Если вы достаточно давно занимаетесь разработкой ПО, то, вероятно, сталкивались с такой ситуацией: CRUD-приложение, обслуживающее небольшую группу пользователей, развёрнутое в кластере Kubernetes и вдобавок с половиной функций CNCF. В теории выглядит впечатляюще. В реальности же это машина Руба Голдберга, решающая задачи, которых у команды на самом деле нет.
В качестве противоположного примера возьмём Levels.fyi. Сегодня этот сайт помогает миллионам разработчиков сравнивать зарплаты и карьерные перспективы, но в начале его «бэкендом» были просто Google Формы, сохраняемые в Google Таблицы. Никаких микросервисов, никакого Kubernetes, никакой шины событий. Самые простые инструменты, которые можно придумать. Такая легковесная система обеспечила владельцам сервиса скорость её развития. Они проверили жизнеспособность идеи, расширили аудиторию и начали вкладываться в более сложные системы только тогда, когда стало ясно, что продукт рабочий. Иными словами, простота не стала для них препятствием, а превратилась в залог успеха. Стоит также помнить о том, что некоторые из самых сложных инфраструктур изначально были очень простыми: например, Airbnb, Facebook*, Reddit. Прежде, чем завоевать всемирную популярность, они были фрагментарными монолитами.
Всем нам свойственно подхватывать синдром главного героя. Рано или поздно архитектура в большей мере становится не решением текущих задач, а защитой от потенциальных будущих проблем. Кажется, что каждый новый проект должен начинаться с полного набора распределённых систем, вне зависимости от того, разрастётся ли приложение до масштабов, достаточных, чтобы оправдать их необходимость. Разумеется, при этом команды начинают тонуть в сложности, затратах на облачные услуги и низкой скорости выпуска релизов.

Я не против продуманной, хорошо спроектированной архитектуры, но нужно и не забывать о здравом смысле. Лучшие системы из тех, что я видел, не были самыми сложными. Почти всегда они были самыми подходящими для задачи. Они соответствовали масштабу задачи, росли вместе с бизнесом и оставляли разработчикам возможность развернуться.
Один из моих преподавателей однажды дал мне запомнившийся совет: «Нужно, чтобы люди возненавидели тебя за простоту твоей идеи. Они тоже могли сделать так же. Но именно ты реализовал всё качественно». И это относится не только к научной деятельности. Живым доказательством этого является Levels.fyi. Сайт, которым сегодня пользуются миллионы разработчиков, не был изначально огромной распределённой системой.
Именно в этой точке начинается обсуждение оверинжиниринга. Потому что проблема не в самой архитектуре, а в том, что она применяется без учёта контекста. Когда мы забываем, что первая и основная цель ПО — решение реальных задач реальных людей.
В этом посте мы разберёмся, почему возникает оверинжиниринг, узнаем о реальных затратах на него и о принципах, которые позволят архитектуре не отрываться от реальности. В конце я вернусь к тому, как выглядит простота на практике, и почему её добиться сложнее, она требует большей отваги и даёт больше выгод, чем гонка за сложностью.
Что мы подразумеваем под оверинжинирингом?
Вероятно, вы и сами знаете, что под оверинжинирингом редко понимается написание слишком большого объёма кода. Под ним понимают проектирование системы с бóльшим количеством подвижных частей, абстракций и хайповых технологий, чем требует сама задача. Это похоже на подготовку к цунами, когда на самом деле ожидается лишь большая волна. Разумеется, подготовка к цунами — это совершенно иной масштаб; то же самое относится и к компьютерным системам.
По своей сути, понятие хорошей архитектуры связано с соответствием. Она обеспечивает гибкость, позволяющую менять направление развития, поддерживаемость, чтобы с ней могли работать разработчики в будущем, и масштабируемость, чтобы система могла расти в соответствии со спросом. Оверархитектура — это когда система становится примером сложности ради сложности. Когда проектные решения руководствуются тем, что красивее выглядит в резюме или на техническом докладе, а не тем, что на самом деле нужно бизнесу.
Наверное, вы видели это в реальной жизни:
Стартап с 24 микросервисами, обслуживающими несколько десятков пользователей.
Внутренний дашборд с шиной событий, потому что кто-то прочитал исследования применения Kafka в Linkedin.
CRUD-приложение, работающее в Kubernetes, хотя вполне достаточно было бы простой VM или даже serverless-функции.
Команды, практикующие resume-driven development, выбирающие технологии не потому, что это подходящий инструмент, а потому, что они «впечатлят» работодателя на следующем собеседовании.
Ни один из этих паттернов сам по себе не является чем-то плохим в корне. Шины событий, микросервисы, платформы оркестрации — все они решают реальные задачи в соответствующем масштабе. Но они могут оказаться пустой тратой ресурсов, и я считаю, что в случае преждевременного использования они чаще всего наносят вред. Ирония в том, что оверинжиниринг редко делает системы сильнее; часто он делает их более хрупкими. Каждый лишний сервис, абстракция или слой — ещё один потенциальный источник багов, разрастания затрат и потерянных на отладку часов разработчиков. У меня такое было, я хорошо это знаю. Увы! И такое со мной случалось не один раз!
Оверинжиниринг — это не использование современных инструментов, а несоответствие между архитектурой и реальными потребностями. Это проектирование под масштаб, которого ещё нет, необязательная сложность и вложения в будущее, которое нельзя предсказать.
Почему возникает оверинжиринг?
Если очевидно, что оверинжиниринг приносит так много боли, то почему мы продолжаем им заниматься? На самом деле, причина редко в злом умысле или невежестве. Чаще всего он возникает из-за зашедших не туда благих намерений, неправильных стимулов или человеческой природы.
Вот одни из самых серьёзных, на мой взгляд, причин:
Преждевременная оптимизация
Нам нравится чувствовать себя подготовленными, и особенно это касается разработчиков. Мы любим наихудшие сценарии. В этом нет ничего плохого, но часто не учитывается вероятность их возникновения. Приятно представлять миллионы пользователей с первого дня релиза и готовность архитектуры к будущему. Однако большинство продуктов не ждёт такая судьба. Вместо этого нам приходится поддерживать архитектуру, масштабы которой рассчитаны на несуществующую аудиторию. Вбрасывать деньги в проблему лучше тогда, когда они есть, чем когда они в дефиците.
Resume-driven development
Разработчики амбициозны. Они хотят развиваться. Они хотят получать повышения. Им нужно оставаться в рынке. В этом нет ничего плохого. Изучение Kubernetes или развёртывание микросервисов выглядит в CV лучше, чем спокойная реализация надёжного монолита. Проблема возникает, когда резюме становится важнее, чем продукт. В таком случае эти технологии на самом деле не помогают, потому что разработчик изначально не понимал, зачем вообще ему нужен Kubernetes. Если к нему разработчика привела необходимость, то он будет глубже понимать, почему технология стала необходимым злом. И наоборот: разработчики, занимавшиеся созданием и масштабированием монолитов, часто проявляют себя лучше на собеседованиях, потому что действительно понимают задачу.
Стимулы руководства
Руководители часто награждают за масштаб и сложность. Проще продать им «мы создали распределённую архитектуру с мешами сервисов», чем «мы выпустили простую систему, которая работает». Продвижение по карьере и признание часто становятся следствием первого, даже несмотря на то, что второе приносит больше пользы. Очевидно, всё зависит от организации, но в той или иной степени это утверждение справедливо для всей нашей отрасли.
FOMO и погоня за трендами
Никто не хочет работать в команде, продолжающей разработку PHP-монолита, пока все вокруг говорят о мешах сервисов и ИИ-помощниках. Но погоня за трендами только для того, чтобы выглядеть современно, может загнать вас в ловушку инструментов и паттернов, не соответствующих вашим задачам. Именно поэтому «скучное» — это хорошее. Под скучным большинство подразумевает то, что надёжно работало десяток лет. Оно меняется не так быстро. И если это сработало почти у всех, то, вероятно, сработает и у вас. Ваше ПО, скорее всего, не настолько уникально.
Неправильно расставленные приоритеты
Иногда команды выполняют оптимизацию в сторону того, что интересно, а не того, что полезно. Увлекательнее решать сложные технические головоломки, чем связывать скучную бизнес-логику. Опасность заключается в том, что клиентов не волнуют ваши абстракции. Им важно, решает ли ваш продукт их проблему.
Когда я в прошлой жизни работал над биллинговым движком, то вложил в него все известные мне best practices: паттерны, абстракции, архитектуру, рассчитанную на масштабирование. Я сделал всё идеально. А потом нам пришлось отлаживать эту систему. Коллега был вынужден погрузиться на пять слоёв вглубь просто чтобы понять, что происходит внутри. Это заставило меня пересмотреть своё отношение. Я создал не изящную архитектуру, а большую спагетти-вселенную. Сделав шаг назад, я осознал, что вся система могла уместиться в одном файле. И я заставил коллегу пройти через всё это, устроив ему когнитивную перегрузку без малейшей на то причины.
Если соединить всё это, становится понятно, почему у нас в конечном итоге получаются современные бесконечно масштабируемые архитектуры. В каждом отдельном решении есть логика, но накопительный эффект влияет на систему сильнее, чем это необходимо.
Стоимость оверинжиниринга
Если задуматься об оверинжиниринге, то можно сразу понять, что проблема не только в красивых диаграммах архитектуры. Оверинжиниринг влечёт за собой реальные траты. Некоторые из них проявляются сразу же, другие медленно мучают разработчиков в течение месяцев или лет.
До сих пор помню, как, работая в AWS, обнаружил, что в проекте используется DynamoDB. В DynamoDB нет ничего плохого, это мощный инструмент. Но в том случае на самом деле нам нужны были join. Модель данных не была особо сложной. Я не понимал, почему недостаточно старого доброго MySQL. Вместо него команда загнала себя в ловушку системы, усложнявшей простые запросы, замедлявшей работу и добавившей необязательную сложность. Но как вы не понимаете, нам ведь нужно было масштабироваться!
Давайте рассмотрим различные аспекты трат, связанных с оверинжинирингом.
Замедленный выпуск
Каждый слой абстракции, каждый дополнительный сервис, каждый «рекомендованный» фреймворк добавляет инерции. Сегодня я крайне скептично отношусь к добавлению чего-то нового, если оправданность этого не доказана. И под доказанностью я не имею в виду «доказано AWS или Google». Я имею в виду, что обоснованность использования доказали маленькие команды, маленькие проекты в реальных условиях, похожих на наши. Фичи, на которые должна требоваться неделя, растягиваются на месяцы. Команды тратят больше времени на соединение разных частей, чем на привнесение ценности.
Хрупкость, замаскированная под устойчивость
Иронично то, что системы, спроектированные выглядеть надёжными, часто становятся хрупкими. Каждая подвижная часть — это новая точка отказа. Я видел архитектуры, в которых единственная неправильно настроенная очередь валила всю систему. Сложность множит режимы отказа. Чем больше добавляешь, тем меньше на самом деле получаешь.
Кроме того, каждый компонент нужно мониторить и поддерживать. Даже нечто столь «простое», как апгрейд библиотеки, может превратиться в кошмар. И могу сказать по собственному опыту: апгрейд одной библиотеки может вызвать совершенно неожиданные поломки. То, что на белой доске выглядит, как устойчивость, оборачивается в продакшене хрупкостью.
Повышение затрат
Оверинжиниринг высасывает деньги. Ваши счета могут взлететь до небес не потому, что у вас есть пользователи, а потому что работают кучи простаивающих сервисов, не нужных никому. Вы платите за машины, которые стоят и работают вхолостую.
Есть ещё и скрытый налог в виде зарплат. Вы обучаете разработчиков инструментам, которыми они никогда больше не будут пользоваться, и сжигаете циклы просто на поддержание жизни системы. Каждую зависимость, каждый сервис, каждую абстракцию нужно патчить, апгрейдить и обслуживать.
Потеря скорости разработки
Отладка между микросервисами — непростая задача. Изучение слоёв паттернов или ожидание пересборки десятка сервисов конвейерами CI гасит импульс. То, что в монолите могло быть двухчасовым исправлением бага, растягивается на двухдневное испытание.
И вот ещё в чём загвоздка: чтобы понимать происходящее, вам понадобится гораздо больше инструментария. Невозможно просто подключить отладчик и увидеть, что творится. Один сервис вызывает другой, половина этого происходит в переходных состояниях, логи разбросаны по разным местам.
Риски для бизнеса
Главная цена оверинжиниринга заключается в том, что продукт не выпускают никогда или выпускают слишком поздно. Стартапы погибают, не успев найти для своего продукта нишу на рынке. Большие компании начинают пробуксовывать, пока конкуренты обгоняют их и съедают всё. Клиентам не важно, насколько продумана ваша архитектура, если они не видят фич.
Эту боль я и сам испытывал многократно. Думаю, именно поэтому в Amazon для руководства существует принцип Deliver Results. Это напоминание: делайте упор на результатах, а не на рюшечках. Первый Kindle не был идеальным. Наверно, он даже был далёк от этого. Но его выпустили. И потребители его покупали. Amazon училась и со временем выросла в отдельный рынок. Если бы компания ждала, пока продукт станет идеальным, то возможность могла быть упущена.
Жестокая правда заключается в том, что большинство команд терпит неудачу не из-за невозможности масштабирования архитектуры до миллионов пользователей. Они терпят неудачу, потому что их архитектура слишком тяжела и не позволяет им двигаться.
Монолиты и микросервисы
Споры о монолитах и микросервисах — отличный пример для понимания оверинжиниринга.
Когда-то монолиты были стандартом по умолчанию: всё находилось под одной крышей. Фронтенд, бэкенд, бизнес-логика и доступ к базам данных были объединены. В маленьких проектах и первых стартапах такая простота была благом. Можно было быстро выпускать продукты, отлаживать их единой трассировкой стека и развёртывать всё за раз.
Однако у монолитов имелись собственные проблемы, возникавшие с ростом систем и команд:
Одно небольшое изменение требовало пересборки и повторного развёртывания всего приложения.
Единственный вылет мог положить всю систему.
Большие команды могли наступать друг другу на пятки, замедляя выпуск.
Масштабирование по принципу «всё или ничего»: невозможно масштабировать только часть, находящуюся под давлением (допустим, систему платежей).
Микросервисы должны были устранить эти проблемы. При расселении большого дома на квартал из мелких домишек каждый сервис мог:
Развёртываться индивидуально.
Масштабироваться отдельно.
Разрабатываться отдельной командой.
При необходимости использовать свой технологический стек.
Звучит отлично, и для гигантов наподобие Google или Netflix так и было. Но у большинства команд микросервисы создают новые проблемы:
Из-за большего количества подвижных частей усложняется отладка и увеличивается число режимов отказа.
Вызовы функций заменяются сетевыми вызовами, что добавляет задержки и необходимость повторных попыток.
Мониторинг, логгинг и тестирование превращаются в распределённый кошмар.
Сложнее становится реализовать целостность данных между сервисами.
Раздувание сред разработки. Для тестирования одной фичи требуется полдесятка сервисов.
Иными словами, микросервисы не устраняют сложность. Если говорить откровенно, они лишь перераспределяют её. Часто теряется один нюанс: микросервисы решают проблемы, которых нет у большинства команд. Они имеют смысл в случае больших команд, огромного трафика или строгих потребностей в масштабировании. Но если вы небольшой стартап или внутренняя команда скромных размеров, то хорошо структурированный монолит (или модульный монолит) часто обеспечивает 90% преимуществ микросервисов без эксплуатационного оверхеда.
Хорошее эмпирическое правило: начинайте с монолита и правильно реализуйте разбиение на модули. Вырезайте из монолита микросервисы, только если на то есть причина.
Принципы, позволяющие избегать оверинжиниринга
Как же оставаться честным с самим собой? Как провести границу между продуманной архитектурой и ненужным шумом? За годы работы, благодаря множеству ошибок и шрамов я выработал принципы, которые можно использовать в качестве защитного механизма. Они не гарантируют простоты, но повышают ваши шансы на успех.
Вот некоторые из принципов, к которым я возвращаюсь, когда не хочу создавать хаос и жалеть о нём.
Начинайте с простого. Меньше — значит быстрее. Всё должно быть скучным. По умолчанию выбирайте наименьший элемент, который способен работать: единственный репозиторий, модульный монолит, одна база данных, одна очередь (или её отсутствие). «Скучное» — это проверенное, задокументированное, то, под что легко искать людей на вакансии, и стабильное в течение лет, а не недель.
YAGNI > подготовка к будущему. Не стройте системы под масштабы, которых у вас ещё нет. Добавляйте сложность только тогда, когда у вас есть доказательства (нагрузка, команды, SLA), что она потребуется.
-
Правило трёх (для абстракций и сервисов).
Не добавляйте новую абстракцию, пока не возникнет третий реальный случай её необходимости. Не разбивайте сервис на части, пока не возникнет третий проблемный момент (задержка развёртывания, споры в команде, горячие точки).
Доказательства важнее изящества. Создавайте архитектуру на основании данных: реальных задержек, реальных бюджетов на ошибки, реальных сложностей с обслуживанием по вызову, реальных выставляемых счетов. Если вы не можете замерить величину проблемы, значит, вы просто гадаете.
Сначала выберите модульный монолит. Границы устанавливайте в процессе (модули, пакеты, чёткие интерфейсы). Обращайтесь с интерфейсами модулей, как с внешними APIs.
Проектируйте с расчётом на удаление. Каждый новый компонент должно быть легко вырезать. Заранее документируйте «план демонтажа» (зависимости, путь миграции, откат). Если вы не можете удалить элемент, он станет вашим врагом.
Одностраничные RFC, тайм-боксированные спайки. Перед добавлением технологии напишите одностраничный документ: задача, варианты решения, затраты, влияние на эксплуатацию, критерии завершения. Если уверенности по-прежнему нет, проведите спайк на один-два дня. Выпускайте то, чему научились, а не платформы.
Сохраняйте малую площадь операционной поверхности. Каждая новая среда исполнения, очередь или база данных приводит к умножению нагрузки на дежурных разработчиков, патчинг, наблюдаемость и затраты. По мере возможности консолидируйте среды исполнения и инфраструктуру.
Стабильные контракты выигрывают у общих баз данных. Определите чёткие границы API/контрактов. Избегайте паттернов межкомандного доступа к базам данных. Если ваши контракты будут оставаться стабильными, вы сможете быстро двигаться без мешанины распределённых систем.
Сначала оптимизируйте работу так, чтобы повышалась velocity разработчиков. Локальная разработка за <10 минут. CI меньше, чем за 10 минут. Одна команда для запуска, одна команда для развёртывания. Если это упустить, то сложность победит.
По умолчанию используйте механизмы защиты от трат. На ранних этапах устанавливайте бюджеты/алерты (траты на среду, на сервис). Устраняйте простаивающие мощности. Сложность, не оправдывающая себя, должна быть отключена.
Наблюдаемость должна соответствовать масштабам. Начинайте с логов и метрик, добавляйте трассировки, только когда это необходимо.
Выбирайте используемые по умолчанию технологии и придерживайтесь их. Выберите язык, фреймворк, базу данных, очередь. Если возникнут отклонения, то необходимы короткий RFC и реальная причина (целевые показатели задержек, недостающие возможности библиотек), а не вкусовщина.
Формируйте границы команд так, чтобы они соответствовали чётким границам в системе (а не политике организации). Если команды не связаны с конкретными модулями/сервисами, то вы получите распределённый монолит.
Избегайте распределённых транзакций и используйте их только при крайней необходимости. Выбирайте идемпотентность, повторные попытки и задачи реконсиляции. Если рабочий поток можно сохранить в пределах одной транзакции, то сделайте так.
Небольшие пакетные выпуски, быстрая обратная связь. Выпуски тонкими срезами. Если изменение невозможно развернуть независимо и быстро проверить, значит, ваша архитектура ведёт с вами бой.
Делайте ошибочный путь явным. Хаос возникает из-за неопределённости. Сразу документируйте режимы сбоев, таймауты, повторные попытки и противодавление. Сложность, с которой мирятся — это умножаемая сложность.
Используйте бюджет простоты. При каждом добавлении нового компонента, избавляйтесь от какой-то другой части или консолидируйте её с чем-то ещё. Суммарная сложность должна снижаться, а не увеличиваться.
Здравая культура разработки и поклонение сложности
Самое сложное в борьбе с оверинжинирингом — это не технологии, это всегда культура. В компании могут работать умнейшие инженеры мира, но если её культура вознаграждает за сложность, то каждый раз на выходе вы будете получать раздутые системы. Исключений нет!
В здравой культуре разработки простота — это сила. Руководство подталкивает команды выбирать скучные, проверенные инструменты. Лиды вознаграждают за выпуск и повышение качества для клиентов, а не за размер диаграммы архитектуры. Разработчики могут говорить «нам это пока не нужно», без риска, что их назовут ленивыми или отставшими от трендов. Настоящие герои — это те, кто упрощает, а не усложняет.
Если культура «подсела» на сложность, то всё происходит наоборот. Каждый проект становится шансом похвастаться громкими на данный момент словами: kubernetes, меш сервисов, event-driven. Разработчики пишут взрывающие мозг системы, чтобы впечатлить коллег или ради ярких резюме. Лиды вознаграждают за громко звучащие проекты, потому что благодаря этому на слайдах презентаций они выглядят визионерами. В результате возникает фетиш сложности: системы, которые никто не понимает полностью, затраты, которые никто не контролирует, и velocity, которую никто не может восстановить.
Разница сводится к поощрению. Если вы приветствуете изящество и выпуск готового, то получите легковесные, удобные в поддержке системы. Если главное — это сложность, то возникнет переплетённый хаос, который выглядит красиво в докладе на конференции, но обрушится под весом реальных нагрузок.
Здоровая культура учит разработчиков, что простота — это не движение по короткому пути, а дисциплина. Это когда говорят «нет» новому хайповому инструменту, противятся стремлению к чрезмерному абстрагированию и помнят, что клиентов не волнуют диаграммы архитектуры, им важно, работает она или нет.
В заключение
Оверинжиниринг — это не техническая, а мировоззренческая проблема. Мы купились на сказки клоунов о том, что «сложно» — значит «лучше». На самом деле, сложность медленнее и дороже. Прошедшие проверку временем системы не самые хайповые, они соответствуют задаче, растут вместе с бизнесом и оставляют пространство для свободы разработчиков.
Из историй Levels.fyi, Airbnb и даже первого Kindle можно извлечь простой урок: победу приносит создание не самой большой системы, а самой подходящей. Исполнение важнее, чем изящество. Выпуск важнее, чем бесконечное совершенствование.
У нас, разработчиков и лидов, есть выбор. Мы можем стремиться к сложности ради сложности или создавать культуры, приветствующие чёткость, выпуск готового и положительный эффект. В конечном итоге, клиенты не будут помнить, используете ли вы Kafka, Kubernetes или самый громкий на 2025 год фреймворк. Они запомнят, решил ли ваш продукт их задачу.
Поэтому когда в следующий раз вам захочется выбрать инструмент из инвентаря больших корпораций, остановитесь и спросите себя: каким будет самое простое работающее решение? Этот вопрос спасал меня бессчётное количество раз.
Возьмите в качестве образца конвейер оболочки: небольшие инструменты, каждый их которых хорошо справляется со своей задачей, соединённые простым, но мощным образом. Это и есть изящество. Это и есть проектирование.
* Принадлежит компании Meta, признанной экстремистской и запрещённой в России.
Комментарии (12)

BioHazzardt
20.10.2025 18:18Стартап с 24 микросервисами, обслуживающими несколько десятков пользователей.
Хех, я видел сервер с 30+ микросервисами, крутящимися в докере, причем сервер - двухядерник с 4 GB RAM, там половина оператоса сжиралась в режиме простоя, когда нагрузки вообще не было

Nansch
20.10.2025 18:18Пишем на Си сервисы, компилируем в бинари, которые сидят в памяти, открыв порт, и джейсоны ждут. Тут в принципе даже контейнеры не нужны, если выделить им инстанс целиком. Выглядит такое сетевое взаимодействие довольно просто, что тут может пойти не так?

yaroslavp
20.10.2025 18:18Пойти не так может тот факт, что поиск программиста на си дольше, чем на написание сервиса на ином языке)))

olku
20.10.2025 18:18Согласен что оверинжиниринг это не техническая проблема. Ещё есть влияние руководства, особенно в стартапах с финансированием "премией за масштаб". Сейчас такого все меньше, но совладельцы могут вынуждать строить архитектуру для мифического количества клиентов, которое по их планам вот вот появится. Им надо это показать в отчётности и в системе. За Гугл докс поговорить не удастся.

pon007
20.10.2025 18:18Сделать просто и чтобы нормально работало иногда сложнее/дольше/дороже, чем сваять вроде рабочую монструозину.
А бизнес хочет результат прямщас и , желательно, бесплатно.
Потом конечно кто-то будет плакать, но это потом.

FatherYan
20.10.2025 18:18Сталкивался с огромным оверинжинирингом, который когда потребовался, просто не выполнил свою функцию. Суть:
Для приложения требовался механизм согласований различных сущностей. Немного упрощенно - нужно проверять кому доступны некоторые действия, отображать кнопки типа "Согласовать", "Отказать" и фиксировать результат.
В качестве механизма использовалась Jira с которой приложение общалось по REST API. В теории все красиво - мощный, надежный и гибко настраиваемый механизм. Можно различные workflow делать, гибко разные условия проверять и т. д. и т. п. Для максимальной гибкости, был сделан интеграционный сервис, в котором через конфигурацию настраивалось какие методы Jira и с какими параметрами должны вызываться для каждой операции. Условно - "получить доступные действия для данного пользователя", "Выполнить действие в workflow" (пользователь нажал кнопку и т. д.). Фактически был разработан некоторый собственный макроязык. В ТЗ это громко называлось "Универсальная state-машина" и предполагалось, что только с помощью настроек, можно будет вместо Jira использовать другой движок. Разумеется и в эксплуатации и в разработке все это было крайне сложно. Каждая проблема и доработка требовала глубокого понимания логики работы нескольких разнородных сервисов и систем с кастомными настройками. Отладка - ад. В общем мы быстро пришли к пониманию, что туда лучше вообще не лезть без крайней необходимости.А потом случилось импортозамещение. И мы сначала поверили во фразу "Универсальная state-машина" и угрохали кучу ресурсов, чтобы попытаться вместо Jira прикрутить Битрикс24. А потом поняли, что несмотря на всю суперсложную гибкость настройки, это попросту невозможно, и начали все делать с нуля.
Это идеальный пример, когда собрали все минусы оверинжиниринга, лишних уровней абстракции и в итоге получили ноль плюсов.

monco83
20.10.2025 18:18Поэтому, когда доходит до выдачи прав на кнопочки, я всегда говорю: ну какой вам, к чёрту, ABAC, давайте лучше на коленочке сделаем ровно то, что нужно.

ALexKud
20.10.2025 18:18Правильно писал один товарищ, что стейтмашины это зло. Видимо теперь и вы понимаете это.

northrop
20.10.2025 18:18Зато вписали обьективно заслуженно в резюме опыт работы с кошерными технологиями, создав без пяти минут мордокнигу. А по другому ты слона не продашь (с)

vdudouyt
20.10.2025 18:18Хотят байки, что где-то в стране эльфов есть культура т.н. "венчурных инвесторов". И если товаром является не собственно сам продукт, а сказочка о том, что вот-вот он полетит to the moon так как нашими experienced developers там используются те же технологии что и в FAANG-е, то этот вопрос начинает выглядеть несколько по-другому.
OlegZH
Была бы наука проектирования, можно было бы делать по науке. А, раз, нет науки, то приходится делать, как получится. Кто-то не шибко грамотный и зря городит огород (ну, например, когда достаточно сочинить подходящий SQL-запрос, вместо длинного кода на клиенте). Кто-то гонится за модными технологиями. А, порою, нужно признать и то, что лучше изначально делать что-то сложным (в смысле, составным), чтобы даже простое приложение уложить в некую концепцию, чтобы потом было легче "двигать" её вверх по шкале сложности.