Software Architect · Модуль 05

Декомпозиция — это не раскладывание файлов по папкам. Это выбор границ, внутри которых изменения остаются локальными.

Cohesion · coupling · bounded context · ownership

§ 01

Хорошая граница проходит там, где у системы естественно меняется ответственность, язык или скорость изменений.

Декомпозиция начинается с причин изменения

Если одну дверь постоянно двигают из-за склада, а другую из-за входа для гостей, это разные зоны здания. Их не нужно проектировать как одну стену.

Компонент с high cohesion содержит вещи, которые меняются по одной причине. Компонент с low coupling мало знает о соседях и общается через понятный контракт. Эти два свойства важнее названий паттернов.

Плохая декомпозиция часто выглядит аккуратно в IDE: controllers, services, repositories, utils. Но если маленькая продуктовая правка требует менять пять слоёв и три домена, система всё равно плохо разрезана. Хорошая декомпозиция позволяет изменить checkout, billing или identity без мысленной загрузки всего продукта.

Граница — это ещё и ownership

Карта города бесполезна, если никто не знает, кто чинит мосты, кто отвечает за светофоры и кому звонить при аварии.

Архитектурная граница должна иметь владельца. Если модуль «общий», но меняют его все, он быстро становится зоной риска. Если bounded context принадлежит команде, у неё появляется право менять внутреннюю модель и обязанность держать внешний контракт стабильным.

Поэтому decompositon и team topology связаны. Иногда правильный вопрос звучит не «какой сервис выделить», а «какая команда должна владеть этим потоком end-to-end».

§ 02

Один и тот же домен можно разрезать по таблицам, слоям или бизнес-потокам. Работает обычно третий вариант.

Пример: checkout как вертикальный slice

Касса в магазине отвечает за путь покупки: корзина, цена, оплата, чек. Она не является «слоем кнопок» или «слоем SQL».

В e-commerce checkout может владеть pricing snapshot, payment intent, order draft и failure handling. Catalog остаётся владельцем товаров, identity — пользователей, warehouse — остатков. Checkout не копирует чужую логику, а запрашивает данные через контракты и публикует событие OrderPlaced.

Такой vertical slice удобен: команда понимает пользовательский поток целиком, а изменения в оплате не расползаются по всем подсистемам.

Антипример: декомпозиция по техническим слоям как единственная граница

Если все повара режут овощи в одной комнате, жарят в другой, а солят в третьей, простой заказ начинает требовать координации всего здания.

Система разделена на user-service, order-service, payment-service, но внутри каждого сервиса есть общий common-domain, общая база и shared validators. Формально сервисы есть, фактически границ нет.

Ещё хуже, когда команды владеют слоями: frontend team, backend team, database team. Любая фича становится проектом координации. Это увеличивает lead time и cognitive load.

Самопроверка
  • Что является причиной изменения этого модуля? - Может ли команда изменить его без согласования с пятью соседями? - Есть ли у границы владелец? - Какие данные и инварианты действительно принадлежат этому контексту?