Features
Когда использовать?
Когда в проекте становится сложно найти границы конкретных пользовательских сценариев, из-за чего страдает контролируемость и переиспользование логики
Используйте, только если уверены, что дополнительное разделение по фичам поможет вашему приложению, а не вызовет слишком много недопонимания и скепсиса! (вместо этого, можете хранить подобную логику прямо в виджетах) ⚠️
Описание
Каждая фича - часть бизнес-логики, при этом обязательно имеющая смысл и ценность для конечного пользователя
ProductList
,OfficeMap
- вряд ли можно назвать фичамиWalletAddFunds
,AddToCart
- уже больше смысла для конечного пользователя
При этом:
- для построения логики используются нижележащие слои
shared
,entities
- одна фича не может импортировать другую
- Если возникла такая необходимость - зависимость нужно переносить на слой выше / ниже, либо решать через композицию через children-props
- фичи не могут быть вложенными, но при этом могут объединяться общей папкой, т.е. структурно
- При этом нельзя создавать промежуточные файлы, нужные именно для конкретной группы фич
- Можно использовать только файлы реэкспорты
Структура
└── features/{slice}
├── lib/
├── model/
├── ui/
└── index.ts
Таким образом, фича хранит информацию о том:
- Какие данные нужны для её работы
- По каким правилами происходят изменения данных
- Какие сущности нужны для полного построения фичи
- Как данные представлены для пользователя
Правила
Одна фича = одна функциональность
В фиче находится код, который реализует одну полезную функциональность для пользователя.
Структурная группировка фич
Часто возникает необходимость собрать вместе ряд несколько связанных по смыслу фич (при этом они могут и должны не импортировать друг друга напрямую)
Методология рекоммендует избегать вложенных фич, т.е. фич - которые сильно связаны под общей оберткой с доп. логикой
Вместо этого - методология предлагает при необходимости - группировать по папкам необходимые фичи (при этом нельзя эти фичи связывать напрямую, папки нужны только для структурной группировки по смыслу)
features/order/ Группа фич
├── add-to-cart Полноценная фича
├── total-info Полноценная фича
- ├── model.ts Общая логика для группы
- ├── hooks.ts Общие хуки для группы
├── index.ts Публичный API с реэкспортом фич
Фичи не должны зависеть друг от друга
Данное правило не всегда получается соблюдать, но количество таких нарушений лучше свести к минимуму.
Как правило, именно из-за пренебрежения этим правилом появляется высокая связность между модулями системы и непредсказуемые сайд-эффекты при разработке.
Одним из способов для решения проблемы является использование entity.
Примеры
С точки зрения кода: не все изменения для пользователя — features
, но все features
— изменения для пользователя.
Смена языка интерфейса приложения
Feature
для пользователя и разработчика.
При этом сама
i18n
логика может использоваться не только в этой фиче, но и даже в сущностях. Поэтому такое стоит скорее располагать вshared/lib
илиshared/config
Позже будет добавлен отдельный гайд
Перевод средств между счетами
Feature
для пользователя и разработчика.
Фильтр по тегам
- Для пользователя:
feature
. - Для разработчика: entity
tags
позволяют реализовать фильтр по тегам внутриfeature
.
Подсказки при заполении полей формы
- Для пользователя:
feature
. - Для разработчика: часть
form
entity.
Авторизация по телефону
import { viewerModel } from "entities/viewer";
export const AuthByPhone = () => {
return (
// для redux - дополнительно нужен dispatch
<Form onSuccess={(user) => viewerModel.setUser(user)}>
<Form.Input
type="phone"
...
/>
<Form.Button
...
/>
</Form>
)
}