Когда фича-команде не стоит трогать код: случай команды для сложной подсистемы
Ваша команда разрабатывает e-commerce платформу. Вы отвечаете за процесс оформления заказа, каталог товаров и страницу профиля пользователя. Всё идет хорошо, пока не требуется изменить модуль оплаты. Внезапно даже самое простое обновление требует трех код-ревью, двух утверждений и молитвы перед деплоем. Одна неверная строка может привести к двойному списанию с клиента или полной потере транзакции. Команда замедляется не потому, что инженеры плохи, а потому что платежный движок — это совсем другой зверь.
Такая ситуация встречается часто. В любом приложении есть части, которые слишком рискованны, слишком специализированы или слишком сложны для безопасной обработки командой общего профиля. Стандартная структура stream-aligned команд отлично работает для большинства фич, но ломается, когда код требует глубоких и узких знаний. Вот тут и приходит на помощь команда для сложной подсистемы (complicated-subsystem team).
Что делает подсистему сложной
Не каждый кусок кода требует выделенной команды. У сложной подсистемы есть особые характеристики. Она редко меняется, но когда это происходит, влияние широко и опасно. Она требует знаний, которые нарабатываются месяцами или годами. Поведение неочевидно: граничные случаи, состояния гонки и тонкие зависимости состояния, которые проявляются только в продакшене.
Вспомните платежный движок, основную схему базы данных, систему биллинга или модуль обнаружения мошенничества. Они сложны не просто из-за большого количества строк кода. Они сложны, потому что цена ошибки высока, а путь к правильному решению узок. Фича-команда, работающая над страницами товаров, не может позволить себе три недели изучать особенности платежного шлюза только ради добавления нового способа оплаты.
Как работает команда для сложной подсистемы
У этой команды одна цель: владеть и поддерживать конкретную подсистему, требующую глубокой экспертизы. Они не создают пользовательские фичи. Они напрямую не отвечают на запросы клиентов. Их задача — поддерживать подсистему стабильной, безопасной и готовой к использованию другими командами.
Модель взаимодействия — X-as-a-Service. Команда сложной подсистемы предоставляет четкий интерфейс, обычно API, который stream-aligned команды могут вызывать, не вникая во внутренности. Платежная команда предоставляет эндпоинты для обработки платежей, проверки статуса транзакции и инициирования возвратов. Фича-команда вызывает эти эндпоинты и идет дальше. Им никогда не нужно знать, как работает соединение с банком или как логика сверки обрабатывает дублирующиеся транзакции.
Эта граница критически важна. Она защищает фича-команду от ненужной сложности, а подсистему — от изменений, вносимых людьми, которые не понимают её до конца.
Когда необходимо сотрудничество
Модель X-as-a-Service хорошо работает для рутинных операций, но иногда фича-команде нужно что-то новое от подсистемы. Например, им может потребоваться возможность частичного возврата, которой ещё нет. В этом случае две команды временно сотрудничают. Фича-команда объясняет требования. Команда сложной подсистемы проектирует изменение, реализует его и расширяет API. Как только новая возможность готова, сотрудничество заканчивается. Фича-команда снова вызывает API, а команда сложной подсистемы возвращается к её поддержке.
Такое временное сотрудничество — не провал модели. Это то, как модель остаётся полезной. Ключевой момент: у сотрудничества есть четкие рамки и определенный конец. Оно не превращается в постоянную зависимость, когда фича-команды ждут команду сложной подсистемы для каждого мелкого изменения.
Как избежать узкого места
Самый большой риск команды сложной подсистемы — стать узким местом. Если каждое изменение в подсистеме требует участия этой команды, фича-команды замедлятся. Решение — серьезно инвестировать в интерфейс. API должен быть гибким, хорошо документированным и спроектированным так, чтобы покрывать типовые случаи без необходимости постоянных обновлений. Команда также должна поддерживать надежный CI/CD пайплайн для своей подсистемы, включая тщательные интеграционные тесты и безопасные стратегии деплоя, такие как blue-green или canary releases.
Когда интерфейс хорош, большинству фича-команд никогда не нужно общаться с командой сложной подсистемы. Они просто используют API и идут дальше. Команда подключается только тогда, когда нужно что-то действительно новое.
Практический чек-лист для выявления сложной подсистемы
Прежде чем создавать команду для сложной подсистемы, проверьте, действительно ли код соответствует профилю:
- Одна ошибка в этом коде приводит к высоким финансовым, безопасностным или операционным потерям?
- Требует ли он специализированных знаний, которые нарабатываются месяцами?
- Меняется ли он редко, но с широким влиянием, когда это происходит?
- Стала бы фича-команда значительно медленнее, если бы ей пришлось владеть этим кодом?
Если на большинство вопросов вы ответили «да», стоит рассмотреть создание команды сложной подсистемы. Если нет — оставьте код в фича-команде и вложитесь в лучшее тестирование и документацию.
Вывод
Команда сложной подсистемы — это не про охрану кода или создание иерархии. Это про защиту как самой подсистемы, так и фича-команд от ненужного риска. Фича-команда остается быстрой, потому что ей не нужно изучать внутренности платежного движка. Подсистема остается безопасной, потому что изменения вносят только те, кто действительно её понимает. Интерфейс между ними — это контракт, который делает всё это возможным. Инвестируйте в этот интерфейс, и обе команды выиграют.