Почему два слоя модулей
Features и services — не недоработка. Почему не widgets/entities и не шесть слоёв FSD.
Короткий ответ
В графе зависимостей есть одно качественное различие: «от меня никто не зависит» vs «от меня зависят». Features — первое, services — второе. Дополнительные слои (widgets, entities, processes) нарезают непрерывный ранг по размеру и смыслу — спорить о границах бесконечно, а проверить их машиной нельзя.
Непрерывный ранг vs дискретные обязанности
Любой модуль можно расположить на оси «сколько от него зависит код». Это непрерывная шкала. Но обязанности меняются скачком в одной точке:
| Feature | Service | |
|---|---|---|
| Входящие рёбра от модулей | Нет | Есть |
| Стабильность API | Можно менять свободнее | Зависимые ломаются |
| Promotion | — | Feature переезжает сюда |
| Предикат | Проверяем: нет входящих рёбер | Проверяем: есть входящие рёбра |
Добавить widgets между features и services — значит ввести границу, у которой нет разных машинных обязанностей с обеих сторон. Это вкус, не правило.
Почему не FSD с 4–6 слоями
Feature-Sliced Design режет код по семантике: entities, features, widgets, pages… Команды месяцами спорят: «корзина — entity или feature?». DMA отвечает: не спорим — смотрим на граф.
- Нет входящих рёбер от модулей →
features/ - Появились входящие рёбра →
services/ - Переносимый код →
shared/
Семантика продукта остаётся в именах папок (checkout, catalog), а не в ранге слоя.
Почему не одна плоская modules/
Без разделения feature/service предикат входящих рёбер бессмысленен. Вы не узнаете автоматически, что модуль стал общим и его API пора стабилизировать. Promotion — осознанный момент дизайна: API, выросшее для одного потребителя, вынуждено стать контрактом для многих.
services/ не с первого дня
Отложенная папка: пока все модули — изолированные фичи, services/ не нужна. Правила про services «спят». Это снижает порог входа — не создаёте пустые слои «на вырост».
Честные компромиссы
DMA проигрывает, когда:
- команде нужна жёсткая семантическая таксономия для онбординга («всё про пользователя — в entities»);
- продукт огромный, и горизонтальные домены (
billing/,catalog/) важнее вертикального ранга — DMA рекомендует split по доменам внутриservices/, а не новые слои.
DMA выигрывает, когда:
- хотите правила, которые CI проверяет без интерпретации;
- устали от «а это widget или feature?» на каждом ревью.
Сравнение таблицей — DMA vs FSD.
Связанные темы
- Слои — предикаты и направление импортов
- Эволюция кода — promotion feature → service
- Инструменты:
feature-has-inbound,service-no-inboundв dma check