Derived Modular Arch
Deep Dive

Services vs Shared

Где проходит граница между продуктовым сценарием и переносимой инфраструктурой.

Короткий ответ

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

Эвристика одной фразой

Может ли этот код жить в другом продукте без изменений?

  • Даshared/
  • Нетservices/

Кнопка, formatCurrency, базовый HTTP-клиент — shared. Корзина, checkout-flow, права на заказы продукта — services.

Почему оба слоя с входящими рёбрами

И services/, и shared/ имеют входящие рёбра от модулей. Различие не в графе, а в смысле кода:

ServicesShared
Знает продуктДаНет
Примерcart, session, permissionsButton, format-date, api-client
public/Да, плоскийНе нужен — весь слой публичен
Группы внутриСегменты модуля (ui, model…)ui/, lib/, api/, model/, domain/

Типичные ошибки

Слишком рано в shared. Вынесли хелпер «на будущее» — через месяц shared/lib превращается в свалку. Правило второго использования: сначала колокация, потом перенос при втором потребителе.

Продуктовый код в shared. shared/ui/cart-badge.tsx знает про корзину — это feature или service, не shared UI primitive.

Service без потребителей. Модуль в services/, от которого не зависит ни один другой модуль — нарушает предикат (service-no-inbound). Демотируйте обратно в feature или удалите.

Feature, от которого все зависят. Checkout импортируют catalog и profile — это service, не feature (feature-has-inbound).

Как принять решение на практике

  1. Появился второй потребитель? (dma doctorshared-candidate)
  2. Код про этот продукт? → services/, promotion из feature
  3. Код переносимый? → нужная группа в shared/ (ui, lib, api, model, domain)
  4. Сомневаетесь? Оставьте в feature до появления второго потребителя — колокация дешевле ошибки

Группы shared

shared/
├── ui/       # кнопки, инпуты — без знания домена
├── lib/      # даты, форматирование, storage
├── api/      # базовый HTTP-клиент, interceptors
├── model/    # query client, env, feature flags
└── domain/   # общие бизнес-типы (User, Money)

Подробнее — Shared.

Services и домены

Когда services/ разрастается, режьте горизонтально (domains/billing/, отдельные пакеты) — не добавляйте новые вертикальные слои. Сигнал dense-services в doctor подскажет, что пора делить.

Связанные темы

On this page