О зацеплении на одном примере
Есть особое состояние в жизни сервиса: изменение назрело, все согласны, что оно нужно, а сделать его нельзя. Не «сложно», а именно нельзя. Так у нас произошло с переездом на новую таблицу.
Сначала всё казалось удобным. Бэкенд ничего не маппит: принял запрос → собрал SQL → отдал в ClickHouse. Внутри сервиса слои обмениваются словарями с теми же ключами. Репозиторий наружу отдаёт ORM-модели — копии таблицы. Разработка идёт.
За годы в таблице сложился зоопарк: часть колонок snake_case, часть camelCase. Все обещали себе, что «когда-нибудь» наведут порядок.
И вот схема перестала справляться по производительности. Решением было завести новую таблицу и заодно, наконец, привести нейминг к одному стилю.
Тут и выяснилось главное: схема таблицы давно не внутреннее дело модуля хранения. Имена колонок совпадают с параметрами gRPC и ключами словаря между модулями. Клиент вынужден передавать фильтры теми же именами, что и колонки в таблице.
Переименовать? Сломаются фронт, интеграции и соседние модули. Добавить столбец? Добавится легко, но мгновенно протечёт в фильтры и ответы, а вытащить обратно уже не получится.
Первый вариант - мигрировать всех потребителей, но это долго. Второй - сохранить формат старой таблицы. Выбор сделали за нас сроки: дедлайн по производительности поджимал, а миграция требовала большого рефакторинга.
Новая таблица работает быстрее - и воспроизводит старую схему со всем зоопарком. Единственный шанс привести её в порядок упущен: неаккуратный нейминг теперь живёт в свежей, только что созданной таблице. Консервация стала только прочнее.
В терминах архитектуры это зацепление (coupling) - сила зависимостей между модулями. Не путать со связностью (cohesion) - это про фокус модуля на одной задаче. У нас схема хранения протекла сквозь все слои - классическая протечка абстракции.
Какова цена удобства, с которого всё начиналось? Отсутствие выбора. Решение о новой схеме было принято в момент, когда колонки протекли в контракты. Дедлайн лишь подписал то, что было решено без нас. Так старые решения протаскиваются в новые артефакты: схема заморожена не для текущей таблицы, а для всех следующих. Переезд на новое хранилище не обнулил долг, а взял его с собой.