Привет! Меня зовут Егор Подольский, я фронтенд-инженер в Авито. Знакомство с Feature-Sliced Design я начал не так давно. Её используют немногие, а я попробовал применить её, и влюбился. Решил рассказать о FSD, потому что считаю этот подход удобным и перспективным.
Featured-sliced Design — это свод правил и требований к организации кода, который делает разработку легче. Методология разработана для фронтенд-приложений, но отдельные концепции из FSD можно использовать и для бэкенда.
Лучше всего суть методологии раскрывается в проектах среднего размера, так как FSD — это про организацию. В одностраничных приложениях, с парой папок, не получится прочувствовать все преимущества методологии, а в слишком больших, наподобие Google Cloud, её будет недостаточно для построения архитектуры. Но FSD может стать отправной точкой, с которой можно начать разработку.
Featured-sliced Design не привязана к конкретному фреймворку или state-менеджеру, поэтому её можно внедрять в командах с разным стеком. Примеры проектов, которые применяют FSD, есть на сайте разработчиков методологии.
Структура Featured-sliced Design
Главное правило, на котором строится методология: все элементы кода разделены по зоне ответственности (слои), предметной области (слайсы) и техническому назначению (сегменты).
Семь слоёв делят код по зонам ответственности. Они строго стандартизированы во всех проектах: в любой команде каждый слой будет отвечать за одно и то же.
Весь код проекта распределяется между слоями по принципу: чем выше слой, тем сильнее он привязан к предметной области конкретного приложения. Нижний слой наиболее абстрактный, поэтому его можно использовать для разных проектов.
В каждом слое находятся слайсы. Они разделяют код по предметной области, к которой относится та или иная функция. Это облегчает поиск нужного элемента в проекте.
В слайсах находятся сегменты, которые делят код по техническому назначению. Один из них — Public API, который нужен для импорта других сегментов наружу. То есть, мы можем инкапсулировать логику внутри слайса. В остальном сегменты не стандартизированы. Чаще всего встречаются:
ui — визуальное представление;
model — бизнес-логика;
lib — утилиты, хуки, функции-помощники;
constants;
types;
api — работа с API.
Какие бывают слои и зачем они нужны
Shared — слой для абстрактного, переиспользуемого кода. Это могут быть иконки, отображение кнопок, вспомогательные функции и утилиты, которые неоднократно применяются в разных местах приложения.
Важное отличие слоя Shared от остальных: в нём нет слайсов. Он состоит из сегментов, которые мы можем многократно переиспользовать во всем приложении.
Entities — слой для конкретных бизнес-сущностей. Например, для приложения социальной сети это будут: пользователь, пост, комментарий.
Features — слой для элементов кода, которые определяют, как пользователь взаимодействует с бизнес-логикой. Это различные кнопки, выпадающие меню, селекты и всё остальное, что несёт бизнесовую логику и с чем можно взаимодействовать.
Есть важное правило: одна фича должна выполнять одну задачу. Мы не можем использовать её для разных случаев, иначе это нарушит концепцию инкапсуляции логики.
Widgets — опциональный слой, который связывает сущности и фичи. Он помогает собрать готовый смысловой блок из разных элементов.
Виджеты позволяют расширять функциональность сущности. Например, пост в сообществе и пост на странице пользователя в социальной сети выглядят одинаково. При этом кнопки лайка на них выполняют немного разные функции. На странице пользователя кнопка отправляет уведомление конкретному человеку, а в сообществе — всем пользователям.
Pages — также композиционный слой. Он нужен, чтобы собирать из виджетов, сущностей и фичей полноценные страницы приложения. Главное правило для страниц — они должны быть максимально «тонкими», не содержать дополнительную бизнес-логику. Весь код мы должны реализовать на слоях ниже.
Processes — опциональный слой, который используется крайне редко. Он нужен, если бизнес-логика предполагает использование несколько страниц в одном процессе.
Это может быть аутентификация пользователя по телефону. На одной странице человек вводит номер телефона и пароль, на другой — подтверждает номер, на третьей — вводит капчу.
App — это самый верхний, инициализирующий слой. Он содержит корневой компонент, глобальные типы, стили, стейт и оборачивает приложение в провайдеры и контексты — то, что присуще проекту в общем.
Как понять, в какой слой поместить код
Не всегда бывает понятно, к какому слою отнести ту или иную сущность. А сделать это нужно сразу — до того, как начнёшь писать код. На такой случай в документации есть список вопросов, который помогает верно распределить сущности:
Также в документации есть таблица импорта: какие слои можно импортировать в каждый из остальных слоев. Например, элементы Shared можно использовать на любом другом слое, но в него ничего нельзя добавить. Слой App, наоборот, способен принимать в себя все другие слои, но никуда не импортируется.
Почему FSD лучше обычного способа организации кода
Слои в Featured-sliced design группируются так, чтобы сделать поток данных в приложении линейным и однонаправленным. Это позволяет избежать неявных связей между модулями.
Можно понять, как это работает, если сравнить структуру кода в стандартном варианте и в варианте FSD.
Допустим, у меня есть задача изменить один компонент. Для этого мне нужно найти его в папке «компоненты» — это само по себе бывает непросто, если их много.
Затем мне нужно поправить экшены, константы, другие элементы стейта, которые связаны с моим компонентом. Для этого каждый раз нужно выходить на верхний уровень вложенности в папку src, искать папку constants и в ней — нужные файлы. Затем переходить в actions и снова там искать нужный экшен. Так происходит, потому что в большинстве проектов нет разделения сущностей по бизнес-предназначению.
Получается, что изменяя один компонент, я затрагиваю область всего проекта. Я вынужден исправлять что-то в разных частях кода и постоянно рискую повлиять на что-нибудь ещё.
Такое состояние приложения можно охарактеризовать как слабую связанность и слабую зацепленность. То есть, между модулями нет понятных и явных связей.
В отличие от обычной структуры, FSD поддерживает сильную связанность внутри модуля.
Например, у нас есть страница продукта, которая использует в себе фичи и виджеты. Фичи используют сущности, а те, в свою очередь, Shared-слои.
Если мне нужно будет что-то изменить в деталях продукта, то я не смогу повлиять на рекомендации, потому что эти сущности не связаны. Можно даже полностью убрать одну ветку и остальное приложение не пострадает.
Такое свойство FSD возможно благодаря принципам объектно-ориентированного программирования:
абстракция и полиморфизм — нижние слои не имеют привязки к предметной области, поэтому их можно использовать для разных целей и реализации разной функциональности;
инкапсуляция — Public API в каждом слое позволяет импортировать основную логику из модуля, а её реализация остаётся внутри;
наследование — вышележащие слои используют и расширяют нижележащие.
Стоит ли внедрять FSD в свой проект
У FSD есть несколько важных преимуществ:
Единообразие. В любой команде, которая следует методологии, код будет организован по одним и тем же правилам. Архитектура стандартизируется и новым разработчикам легче влиться в проект.
Контролируемое переиспользование логики. Каждый компонент архитектуры имеет свое назначение и список зависимостей.
Устойчивость к изменениям и рефакторингу. Код можно менять в каждом модуле отдельно, не затрагивая другие.
Ориентированность на потребности бизнеса и пользователей. Весь код разбит на бизнес-домены, поэтому просто определить, в какой его части расположена та или иная фича. Это позволяет легко адаптировать элементы проекта под разные задачи.
Активное комьюнити. В телеграме есть канал, в котором можно пообщаться с создателями методологии и единомышленниками. Там довольно быстро отвечают на любые вопросы и помогают разобраться в тонкостях FSD. Благодаря этому каналу я уже решил несколько своих кейсов.
Но, конечно, есть и недостатки:
Высокий порог входа по сравнению с классическим способом построения архитектуры. Разработчику нужно постоянно думать, как декомпозировать задачу и к какому слою отнести тот или иной модуль.
Нельзя начать писать компоненты, а потом отрефакторить код. Вместо этого нужно сразу определить, какие сущности, фичи, виджеты будут использоваться в проекте.
Процесс внедрения FSD долгий и дорогой. Придётся создавать специальные линтеры, подходы к код-ревью, следить, чтобы вся команда следовала правилам методологии. Это требует осознанности от каждого человека, потому что если один из команды не станет следовать правилам, то весь проект не удастся поддерживать в рамках методологии.
FSD ещё разрабатывается, поэтому в документации описаны не все возможные кейсы. Но этот минус нивелируется активностью сообщества — разработчики быстро помогают решить сложности и описывают в документации разные сложные ситуации.
FSD — это непростая методология. Для работы с ней нужно подготовить команду и дополнительные инструменты. В перспективе внедрение FSD может ускорить и упростить разработку, но необходимость в нём нужно оценивать, исходя из болей и задач конкретной команды разработчиков.
Если вас заинтересовала методология Featured-Sliced Design, дополнительную информацию смотрите по ссылкам на этой странице.
Предыдущая статья: Домашка на лето: что почитать разработчику