Комментарии 20
Крутая статья, информативно
Спасибо!
А как оказывается из примеров на сайте feature sliced design - todo app'ы. На udemy смотрел такие курсы "сайт кинофильмов за 4 часа".
Здравствуйте, не совсем понял суть комментария, не могли бы вы более подробно описать?
В простых приложениях, например Todo App на React (классика) очень хорошо работают многие паттерны - например можно разбить компоненты на мельчайшие части, прям компоненты по 1 строчке. Т.е. удается добиться максимального Single Responsibility. Однако это не значит что это сработает в продакшене.
Хотелось бы по продакшеннее примера Feature-Sliced Design.
Согласен, на сайте FSD достаточно простые примеры, которые нужны там скорее для ознакомления с базовыми концепциями методологии. Однако методология хорошо себя показывает в рамках моей компании, несколько проектов переведены на FSD.
К сожалению, не могу привести пример проектов по соображениям NDA, однако предлагаю вам ознакомиться с примерами реальных проектов, которые предоставлены на официальной странице гитхаба Feature Sliced Design: https://github.com/feature-sliced/examples (эти примеры и много другое также можно найти по ссылке с доп. информацией в конце статьи https://github.com/egorchh/Feature-Sliced-Design-information#примеры)
Также вы можете ознакомиться с моим пет-проектом. Крупное приложение построенное на FSD - https://github.com/egorchh/production-project. (можно удобно запустить на своем пк)
Пруфов нет.
FSD предлагает более удобную для разработки структуру приложения. Когда все разложено по полочкам, легче найти место для новой фичи или экрана. Сложно спорить с тем, что порядок в структуре проекта более выгоден для разработки.
Даже если мы разобьем весь проект на компоненты по одной строчке, как в вашем примере выше, это не значит что структура будет расширяемой и гибкой. Мы все еще можем столкнуться с высокой связностью модулей проекта между собой, что чревато сайд эффектами при внедрении нового функционала и тд.
Если заинтересованы методологией, советую попробовать внедрить ее в свой проект или написать его с нуля, тогда, уверен, что вы почувствуете преимущества.
Как менеджер по продажам. "У нас в фирме качество." А что за качество, что там - непонятно.
Здравствуйте! Спасибо за статью!
Сейчас внедряю fsd в проект среднего размера. Столкнулся с такой дилеммой, есть глобальный стор, zustand, но непонятно где его держать, если не а app.
Состояние приложения, настройки и тд, должны шарится по всем уровням. Но тогда нарушается направление зависимостей.
В вашем примере я заметил провайдер в app. Возможно даже redux, как вы реализуете механизм глобального состояния в контексте fsd?
Здравствуйте, поскольку не работал с Zustand, приведу пример на Redux Toolkit. Думаю, логика будет идентична.
1 шаг:
Поскольку на все приложение один глобальный стор, его стоит объявить и конфигурировать в app
. На скрине ниже: конфигурируем store
в одноименном файле, также к конфигурации относится не только объявление стора, но и глобальные типы, дополнительные инструменты. В сегменте ui
создаем hoc
с оберткой (hoc тут необязательный, можем просто обернуть компонент в провайдер). StoreProvider
импортируем из app
, оборачиваем в него корневой компонент. Корневой компонент находится все слоев, можно представить его выше слоя app
по иерархии (такое исключение из правил).

app


2 шаг:
Нам нужно работать с глобальным стейтом в компонентах, которые находятся ниже по иерархии слоев:
Посмотрим на примере фичи:
В рамках приведенной ниже фичи, мы создаем слайс loginSlice
, селекторы, если необходимо, asynThunk'и, типы. Все эти сущности относятся только к работе с той частью стора, которая напрямую связана с фичей
То есть работа со с глобальным стейтом инкапсулирована на уровне каждого слайса. Такой подход, не позволяет нам заэффектить ту часть стора, которая не относится к данной фиче.


Надеюсь, что сумел раскрыть суть подхода, если будут вопросы, с радостью расскажу более подробно.
Большое спасибо за развернутый ответ! В таком контексте, когда легко соотнести срез стора с бизнесовой сущностью или виджетом/фичей довольно просто и понятно.
Но допустим мы хотим в глобальном сторе создать сущность counters. Это счётчики которые должны быть доступны в разных местах приложения. Порой один счётчик в нескольких вью или страницах. Эти самые счётчики могут браться из разных entity. Или вообще приходят в отдельном запросе при инициализации приложения.
Или ещё пример. Роутинг. В приложении кроме страниц могут быть разделы у которых уже в свою очередь страницы. Все это должно быть ещё связано с разным боковым меню например. И слой shared не похож на то место которое должно владеть такими данными.
Прошу прощения за долгий ответ, был в отпуске.
Насколько я понял примеры:
1) Пусть в глобальном сторе у нас будут счетчики. Под каждый счетчик мы можем создать свою сущность или сделать единую изменяемую сущность счетчика (в зависимости от того, насколько они отличаются друг от друга). В этой сущности (слой entity) мы как раз будем обрабатывать запрос приходящий с сервера или работать с счетчиками через клиент и посылать данные об их изменении в глобальный стор. А в нужных нам местах брать информацию о счетчиках из глобального стора.
Таким образом мы можем посылать данные в стор и забирать их оттуда без нарушения потока данных. Поскольку, хоть инициализация стора и хранится в слое app
, сам по себе стор распростаняется на все приложение.
2) К сожалению, не совсем понял пример. Роут-конфиг (скрин ниже) также хранится в слое app
. В нашем выпадающем меню, которое, |скорее всего является виджетом, каждый элемент - ссылка <Link/>

Кликаем по ссылке, перемещается по нужному роуту.
Надеюсь, что хотя бы приблизительно правильно понял о чем идет речь в примерах. Если нет, то буду рад более точным примерам, желательно с кодом и схемой структуры.
А можно использовать feautures/todos/api в features/todos/ui ? Или api можно использовать только на слой ниже?
Прошу прощения за долгий ответ, был в отпуске.
Да, конечно. Так как api
и ui
- сегменты и находятся в одном слайсе, они могут использовать друг друга. А вот уже из слайса мы импортируем только то, что нам понадобится на слое выше.
Спасибо за ответ)
А еще не подскажите, как можно реализовать правильно redux или mobx в проекте?
Просто там возникают зависимости сильные и получается что все приходится тащить в shared
Я такой вопрос задавал уже, но там не чего внятного не ответили, только через костыль, может быть вы чего подскажите?)
https://qna.habr.com/q/1302414
Вот в этом комментарии отвечал на схожий вопрос (https://habr.com/ru/companies/avito/articles/752536/comments/#comment_25853686), если из этого ответа будет не до конца понятно, предлагаю ознакомиться с этим проектом (https://github.com/egorchh/production-project). Если ясней не станет, то отпишитесь, пожалуйста, я попробую расписать максимально подробный ответ.
Спасибо большое за ответ, во всем разобрался, единственный момент, а куда переносить
const useAppDispatch и useAppSelector, они ведь экспортируют в себя типы из createConfigure
А useAppDispatch и useAppSelector используются во всем проекте и получается что мы в shared/hooks экспортируем app/provider
Да, к сожалению, это один из кейсов, которые не до конца учтены в методологии. Это можно считать одним из исключений, поскольку, если бы мы задавали useAppDispatch и useAppSelector в слое app, нарушение принципов было бы куда серьезней.
По поводу таких кейсов советую обращаться к ребятам в телеграмм канал, там подскажут компромисное решение. https://t.me/feature_sliced
FSD - рекомендации по написанию кода, так что от них иногда можно отступать. Но не сильно и не часто) Спасибо за замечание!
Feature-Sliced Design – альтернативный подход к организации кода приложений