Компоненты имеют отдельные интерфейсы, но всегда поставляются одним артефактом. Какую архитектурную связанность это создаёт?
Это создаёт связанность поставки и развёртывания: компоненты нельзя выпускать независимо, даже если их программные интерфейсы разделены. Изменение одного компонента требует совместной сборки, проверки и обычно выпуска всего артефакта.
Такая граница является логически модульной, но не является независимой границей поставки. Поэтому формальное разделение компонентов не гарантирует независимой эволюции системы.
По мере роста программных систем команды начали разделять код на модули, чтобы локализовать изменения и уменьшить область регрессионного тестирования. Следующим шагом стало разделение не только исходного кода, но и жизненного цикла компонентов: сборки, выпуска и развёртывания.
Монолитный артефакт часто выбирают ради простоты эксплуатации и согласованности версий. Однако при большом числе компонентов он превращает технически независимые изменения в общий процесс поставки.
Предположим, компонент платежей и компонент уведомлений имеют отдельные интерфейсы, но входят в один пакет, который выпускается целиком. Небольшое изменение в уведомлениях потребует пересборки, полного набора проверок и развёртывания платежной части, даже если она не менялась.
Это увеличивает время выпуска, размер зоны риска и вероятность того, что несвязанное изменение задержит или заблокирует релиз. Дополнительный риск возникает, если команды начинают избегать частых изменений, объединять их в крупные релизы или выполнять ручные согласования.
Механизм связанности здесь задаётся не вызовами во время выполнения, а единицей поставки. Пока несколько компонентов находятся в одном артефакте или обязаны проходить единый релизный процесс, их версии, проверки и откат практически связаны.
Важно отличать несколько уровней границ:
Для уменьшения связанности компоненты можно выпускать отдельными артефактами и иметь независимые конвейеры поставки. Но этого недостаточно само по себе: нужны совместимые контракты, обратная совместимость изменений, независимые миграции данных и понятные процедуры наблюдения и отката.
Полностью независимое развёртывание имеет цену. Возрастают операционная сложность, требования к мониторингу, управлению версиями и тестированию взаимодействий. Поэтому не всякую логическую границу следует превращать в отдельную единицу поставки: стабильные и тесно связанные части иногда разумно оставлять в одном артефакте.
В платформе заказов модули расчёта доставки и уведомлений имели отдельные интерфейсы, но выпускались одним пакетом. Команда уведомлений хотела менять шаблоны несколько раз в неделю, а каждый релиз требовал полного регрессионного тестирования всей платформы.
Рассматривались три варианта. Сохранение общего артефакта было самым простым в эксплуатации, но сохраняло задержки и общий риск. Разделение только исходных модулей не помогало, поскольку единый конвейер и пакет оставались прежними. Полное разделение поставки давало независимость, но требовало контрактных проверок, мониторинга и отдельного управления версиями.
Выбрали поэтапное разделение: уведомления стали отдельным артефактом с версионируемым контрактом, а расчёт доставки временно остался в общем пакете. Это уменьшило частоту затрагивающих друг друга релизов без преждевременного усложнения всей платформы.
Нет. Независимое развёртывание требует не только разных артефактов, но и возможности отдельно пройти проверки, изменить конфигурацию, активировать новую версию и выполнить откат. Общий релизный поезд, обязательное совместное тестирование или единая ручная процедура могут сохранить связанность даже при раздельной упаковке.
Связанность выполнения возникает, когда один компонент во время работы должен обратиться к другому или зависит от его доступности. Связанность поставки возникает, когда компоненты приходится менять, проверять или выпускать вместе. Эти свойства независимы: компоненты могут иметь частые вызовы, но выпускаться отдельно, либо почти не взаимодействовать во время работы, но быть жёстко связаны общим артефактом.
Он оправдан, если компоненты имеют общий жизненный цикл, изменяются одной командой, требуют согласованной транзакционной или версионной политики и не создают существенных задержек при выпуске. Дефект проявляется не самим фактом совместной упаковки, а тем, что она препятствует нужной скорости изменений, независимому откату или организационной ответственности.