Есть два проекта в двух разных компаниях — оба о том, как затащить дело в крупных корпоратах.
Первый: 50 человек персонала, результата практически нет, еле успели доделать всё за год.
Второй: людей втрое меньше, и по успешности всё сильно лучше, чем в первом проекте.
Давайте посмотрим на суровую реальность. График роста численности персонала в первой компании летит вверх по экспоненте. Они нанимают, нанимают, нанимают. А рядом — график продуктивности (Time-to-Market), который падает с каждым релизом. Фонд оплаты труда растёт, а скорость поставки фич снижается.
Теперь второй график: людей становится не так чтобы сильно больше, а график продуктивности растёт. Почему так?

Очень часто это проблема архитектуры.
Я примерно пять лет занимался системной архитектурой крупных систем, а сейчас ушёл в управление. И вот после этого опыта могу рассказать, в чём там дело, уже детально. Самое интересное, что это не заложенное заранее свойство системы, это именно выбор подхода к проектированию реализуемых сервисов решения. Если очень коротко, это пути зависимостей модулей сервиса. В чистой архитектуре они должны быть направлены только внутрь, в сторону ядра (бизнес-логики системы). Если архитектура выстроена плохо, мы получаем систему с сильной зависимостью от технических деталей реализации. Изменение в одном месте требует правок в пяти других.
Сказать это очень просто, а вот сделать на практике — ГОРАЗДО сложнее. Сложнее не технически, а именно с точки зрения внутренней дисциплины команды и осознания важности проектирования.
Короткий ликбез о модели
Прямо база закладывается ещё в архитектуре конкретного сервиса, в организации его модулей и зависимостей.
Многие декларируют, что микросервисы должны быть независимы и иметь прозрачное доменное и функциональное деление (хотя всё равно на практике это часто не так). Но дальше мало кто следит за тем, чтобы внутри самого микросервиса не образовывался клубок зависимостей. Речь пойдёт именно о «луковой» модели.
В её основе лежит разделение на слои, напоминающее луковицу.
Сущности — ядро. Критические бизнес-правила, которые не зависят ни от чего.
Варианты использования — сценарии работы приложения.
Адаптеры интерфейсов — контроллеры, презентеры, шлюзы.
Фреймворки и драйверы — самый внешний слой — БД, Web, UI, API.
Главное правило — зависимости всегда направлены внутрь. База данных знает о контроллере, контроллер знает о сценарии, но сценарий ничего не знает о базе данных.
Почему так не делают?
Если это база, которой учат, почему мы видим столько проблемных решений? Не все разработчики понимают, зачем нужны эти сложности, или не умеют их применять. Просто банально нет опыта. Надо пару раз наступить на грабли, чтобы это понять. А иногда и пары раз недостаточно.
Жёсткие дедлайны, изменения законодательства (как часто бывает в финтехе), давление бизнеса («надо вчера») и так далее. В такие моменты не до архитектуры. Надо просто быстро нагородить костылей, но найти смелость признать и задокументировать техдолг.
Это может быть беда с общей документацией, онбордингом или просто низкая культура. Ну или личные особенности тимлида, например.
Правильная архитектура всегда стоит дороже в начале
Есть два пути. Разберём на простом примере.
Первый путь — быстрый костыль.
Входящий запрос -> Контроллер -> Скрипт (прямой SQL или вызов) -> База данных.
Цена вопроса — один день.
Это подходит для MVP, который выкинут через неделю. Но если система будет жить, это бомба замедленного действия. Контроллер жёстко связан с базой данных.
Второй — правильный архитектурно, с большим числом слоёв, дороже и дольше в разработке.
Контроллер -> Домен (чистая бизнес-логика) -> Интерфейсы -> Репозиторий (реализация доступа к БД) -> Уровень взаимодействия с данными (ORM/собственный модуль взаимодействия с источником данных).
Но уже три дня. Причём три дня на старте, при реализации нового сервиса приложения. Когда со структурой всё становится понятно, срок заметно уменьшается.
Проблема возникает, когда модули слишком сильно связаны между собой. Тогда изменение в одном месте тянет за собой и другие компоненты — приходится менять не только саму логику, но и интеграции, код, тексты и многое, многое другое.
Поэтому архитектурное решение напрямую влияет на стоимость исправления. На старте дорого, но когда через месяц нужно будет сменить Postgres на Oracle или изменить способ интеграции, мы поменяем это в одном слое. Остальные ломать не придётся.
Без грамотной архитектуры возникает снежный ком из проблем. Все мы знаем, что если ошибка найдена на этапе ТЗ, то на её исправление могут уйти минуты (поправить текст). Если на этапе архитектуры — чуть дольше. Если в продакшене (особенно в релизе № 10, когда ранее реализованная функциональность «обросла» дополнительными требованиями) — это колоссальные затраты (аналитика, архитектура, код, тесты). Плохая архитектура усугубляет обозначенную проблему.

Пример с паспортом
Представьте задачу: нужно проверить паспортные данные клиента.
Например, сегодня мы проверяем паспорт через службы ФМС. Для этого мы отправляем, например, только номер паспорта. Завтра закон меняется, или появляется новый единый сервис. Теперь для проверки нужно отправлять не только номер, но и ФИО, и код подразделения. Протоколы меняются, контракты данных меняются.
Но нашей бизнес-логике всё равно, через какой сервис и каким образом идёт проверка. Ей нужны от этой операции только два флага: «Паспорт действителен» и «Человек отсутствует в нежелательных списках». Это всё, что нужно ядру, чтобы пустить заявку дальше по конвейеру.
Если вы пошли по быстрому пути и прописали логику проверки и вызова ФМС прямо в контроллере или сервисе бизнес-логики, то при переходе на другую внешнюю систему вам придётся всё переписывать.
Если же у вас всё в порядке с организацией модулей и зависимостей, то вы просто пишете новый адаптер. Он на входе берёт нужные данные (ФИО, код), а на выходе отдаёт бизнес-логике те же самые два флага. Ядро системы остаётся нетронутым. Вы меняете интеграционную часть, не ломая бизнес-процесс. Это позволяет легко менять провайдеров (или базы данных, например, MySQL на PostgreSQL), потому что бизнес-логика не зависит от деталей реализации.
Что будет, если так не делать
Бизнес приходит и говорит: «Год назад вы делали такую фичу за неделю. Почему сейчас, когда вас стало больше, вы просите два месяца?»
Ответ «у нас высокая связность кода» бизнес не устраивает.
Ну и дальше, чтобы поддерживать темп разработки на зависимой архитектуре, приходится нанимать людей по экспоненте. Но продуктивность падает, так как новички тонут в зависимостях.
Как уговорить команду тратить 3 дня вместо 1?
Главный аргумент против чистой архитектуры — «долго создавать слои и их интерфейсы взаимодействия». В ответ можно сделать шаблон проекта.
Разработчик нажимает одну кнопку, и у него разворачивается готовая «луковая» структура (Entity, UseCase, Repository). Ему остаётся только вписать логику. Это убивает аргумент «мне лень».
Если бизнес требует «здесь и сейчас», и вы вынуждены сделать костыль — фиксируйте это официально как техдолг. Планируйте рефакторинг. Нельзя вечно жить в кредит. Тут очень много зависит от менеджера, который либо понимает, что это, либо стреляет себе в ногу. Обычно в ИТ-компаниях люди понимают, что такое техдолг, но не до конца осознают его значимость. Это важно проговаривать и объяснять цену вопроса. Тимлиды тоже должны уметь «продавать» архитектуру. Объяснять соседним командам и бизнесу: «Мы потратим сейчас на три дня больше, но, когда вы придёте менять требования через месяц, мы сделаем это за два часа, а не за две недели». Да, это требует умения говорить, но окупается.
Это один аспект медленной разработки, но он, повторюсь, в основе всего, и с ним относительно просто начать работать без изменения структуры организации и архитектуры всего большого проекта.
vadimr
Про важность архитектуры и проблемность техдолга практически все понимают. Но мало кто понимает, какая именно архитектура хороша в каждом конкретном случае. Тут на лозунгах не выехать, надо опыт иметь.
Честно говоря, требования к срокам разработки просто плохо соотносятся с когнитивными возможностями программистов. По опыту видно, что, поразмыслив над задачей 30 лет, можно придумать офигенно красивое и эффективное решение, но очень мало где такой срок вообще возможен. Причём ИИ тут не помощник, так как он просто обобщает популярные практики. А популярные практики таковы, что тяп-ляп – и в продакшен.