Feature-Sliced Design – альтернативный подход к организации кода приложений

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Привет! Меня зовут Егор Подольский, я фронтенд-инженер в Авито. Знакомство с Feature-Sliced Design я начал не так давно. Её используют немногие, а я попробовал применить её, и влюбился. Решил рассказать о FSD, потому что считаю этот подход удобным и перспективным.

Featured-sliced Design — это свод правил и требований к организации кода, который делает разработку легче. Методология разработана для фронтенд-приложений, но отдельные концепции из FSD можно использовать и для бэкенда.

Лучше всего суть методологии раскрывается в проектах среднего размера, так как FSD — это про организацию. В одностраничных приложениях, с парой папок, не получится прочувствовать все преимущества методологии, а в слишком больших, наподобие Google Cloud, её будет недостаточно для построения архитектуры. Но FSD может стать отправной точкой, с которой можно начать разработку.

Featured-sliced Design не привязана к конкретному фреймворку или state-менеджеру, поэтому её можно внедрять в командах с разным стеком. Примеры проектов, которые применяют FSD, есть на сайте разработчиков методологии.

Структура Featured-sliced Design

Главное правило, на котором строится методология: все элементы кода разделены по зоне ответственности (слои), предметной области (слайсы) и техническому назначению (сегменты).

Семь слоёв делят код по зонам ответственности. Они строго стандартизированы во всех проектах: в любой команде каждый слой будет отвечать за одно и то же.

Весь код проекта распределяется между слоями по принципу: чем выше слой, тем сильнее он привязан к предметной области конкретного приложения. Нижний слой наиболее абстрактный, поэтому его можно использовать для разных проектов.

Направляясь по слоям от Shared к App, мы идём от абстрактности к предметной области
Направляясь по слоям от Shared к App, мы идём от абстрактности к предметной области

В каждом слое находятся слайсы. Они разделяют код по предметной области, к которой относится та или иная функция. Это облегчает поиск нужного элемента в проекте.

В слайсах находятся сегменты, которые делят код по техническому назначению. Один из них — Public API, который нужен для импорта других сегментов наружу. То есть, мы можем инкапсулировать логику внутри слайса. В остальном сегменты не стандартизированы. Чаще всего встречаются: 

  • ui — визуальное представление;

  • model — бизнес-логика;

  • lib — утилиты, хуки, функции-помощники;

  • constants;

  • types;

  • api — работа с API.

Какие бывают слои и зачем они нужны

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

Пример из документации FSD: на слое Shared располагаются иконки и кнопки
Пример из документации FSD: на слое Shared располагаются иконки и кнопки

Важное отличие слоя Shared от остальных: в нём нет слайсов. Он состоит из сегментов, которые мы можем многократно переиспользовать во всем приложении.

Пример из моего пет-проекта. Здесь нет слайсов, поэтому сегменты располагаются сразу в слое shared
Пример из моего пет-проекта. Здесь нет слайсов, поэтому сегменты располагаются сразу в слое shared

Entities — слой для конкретных бизнес-сущностей. Например, для приложения социальной сети это будут: пользователь, пост, комментарий.

Пример из документации. Карточка поста — это самостоятельная сущность
Пример из документации. Карточка поста — это самостоятельная сущность
Примеры сущностей из пет-проекта. В слое Entities — слайс Article, а внутри него — сегменты model и ui
Примеры сущностей из пет-проекта. В слое Entities — слайс Article, а внутри него — сегменты model и ui

Features — слой для элементов кода, которые определяют, как пользователь взаимодействует с бизнес-логикой. Это различные кнопки, выпадающие меню, селекты и всё остальное, что несёт бизнесовую логику и с чем можно взаимодействовать.

Пример из документации. Кнопка Following — это фича
Пример из документации. Кнопка Following — это фича

Есть важное правило: одна фича должна выполнять одну задачу. Мы не можем использовать её для разных случаев, иначе это нарушит концепцию инкапсуляции логики.

Пример из пет-проекта. Здесь есть фичи для добавления комментария и авторизации по имени пользователя
Пример из пет-проекта. Здесь есть фичи для добавления комментария и авторизации по имени пользователя

Widgets — опциональный слой, который связывает сущности и фичи. Он помогает собрать готовый смысловой блок из разных элементов.

Пример из документации. Готовая карточка поста собирается на слое Widgets
Пример из документации. Готовая карточка поста собирается на слое Widgets

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

Примеры виджетов из пет-проекта — Sidebar, PageLoader и LangSwitcher
Примеры виджетов из пет-проекта — Sidebar, PageLoader и LangSwitcher

Pages также композиционный слой. Он нужен, чтобы собирать из виджетов, сущностей и фичей полноценные страницы приложения. Главное правило для страниц — они должны быть максимально «тонкими», не содержать дополнительную бизнес-логику. Весь код мы должны реализовать на слоях ниже.

Пример из документации — готовая страница социальной сети
Пример из документации — готовая страница социальной сети
Пример из пет-проекта. В идеальной ситуации здесь были бы только импорты, но у меня есть ещё немного лишней логики
Пример из пет-проекта. В идеальной ситуации здесь были бы только импорты, но у меня есть ещё немного лишней логики

Processes опциональный слой, который используется крайне редко. Он нужен, если бизнес-логика предполагает использование несколько страниц в одном процессе.

Это может быть аутентификация пользователя по телефону. На одной странице человек вводит номер телефона и пароль, на другой — подтверждает номер, на третьей — вводит капчу.

Пример из документации: процесс авторизации проходит через несколько страниц
Пример из документации: процесс авторизации проходит через несколько страниц

App — это самый верхний, инициализирующий слой. Он содержит корневой компонент, глобальные типы, стили, стейт и оборачивает приложение в провайдеры и контексты — то, что присуще проекту в общем.

Пример из пет-проекта. В слое App хранятся стили и провайдеры
Пример из пет-проекта. В слое App хранятся стили и провайдеры

Как понять, в какой слой поместить код

Не всегда бывает понятно, к какому слою отнести ту или иную сущность. А сделать это нужно сразу — до того, как начнёшь писать код. На такой случай в документации есть список вопросов, который помогает верно распределить сущности:

Также в документации есть таблица импорта: какие слои можно импортировать в каждый из остальных слоев. Например, элементы Shared можно использовать на любом другом слое, но в него ничего нельзя добавить. Слой App, наоборот, способен принимать в себя все другие слои, но никуда не импортируется.

Почему FSD лучше обычного способа организации кода

Слои в Featured-sliced design группируются так, чтобы сделать поток данных в приложении линейным и однонаправленным. Это позволяет избежать неявных связей между модулями.

Можно понять, как это работает, если сравнить структуру кода в стандартном варианте и в варианте FSD.

Классическая структура: все элементы лежат в одном каталоге 
Классическая структура: все элементы лежат в одном каталоге 

Допустим, у меня есть задача изменить один компонент. Для этого мне нужно найти его в папке «компоненты» — это само по себе бывает непросто, если их много.

Затем мне нужно поправить экшены, константы, другие элементы стейта, которые связаны с моим компонентом. Для этого каждый раз нужно выходить на верхний уровень вложенности в папку src, искать папку constants и в ней — нужные файлы. Затем переходить в actions и снова там искать нужный экшен. Так происходит, потому что в большинстве проектов нет разделения сущностей по бизнес-предназначению.

Получается, что изменяя один компонент, я затрагиваю область всего проекта. Я вынужден исправлять что-то в разных частях кода и постоянно рискую повлиять на что-нибудь ещё.

Поток данных в классической структуре приложения. Все компоненты влияют друг на друга
Поток данных в классической структуре приложения. Все компоненты влияют друг на друга

Такое состояние приложения можно охарактеризовать как слабую связанность и слабую зацепленность. То есть, между модулями нет понятных и явных связей.

Неочевидные связи в приложении усложняют его поддержку и развитие
Неочевидные связи в приложении усложняют его поддержку и развитие

В отличие от обычной структуры, FSD поддерживает сильную связанность внутри модуля.

Например, у нас есть страница продукта, которая использует в себе фичи и виджеты. Фичи используют сущности, а те, в свою очередь, Shared-слои.

Проект, построенный по методологии FSD: на каждом слое строго определённые элементы кода
Проект, построенный по методологии FSD: на каждом слое строго определённые элементы кода

Если мне нужно будет что-то изменить в деталях продукта, то я не смогу повлиять на рекомендации, потому что эти сущности не связаны. Можно даже полностью убрать одну ветку и остальное приложение не пострадает.

Методология FSD обеспечивает сильную связанность внутри модулей кода и слабую зацепленность между модулями
Методология FSD обеспечивает сильную связанность внутри модулей кода и слабую зацепленность между модулями

Такое свойство FSD возможно благодаря принципам объектно-ориентированного программирования: 

  • абстракция и полиморфизм — нижние слои не имеют привязки к предметной области, поэтому их можно использовать для разных целей и реализации разной функциональности;

  • инкапсуляция — Public API в каждом слое позволяет импортировать основную логику из модуля, а её реализация остаётся внутри;

  • наследование — вышележащие слои используют и расширяют нижележащие.

Стоит ли внедрять FSD в свой проект

У FSD есть несколько важных преимуществ:

  • Единообразие. В любой команде, которая следует методологии, код будет организован по одним и тем же правилам. Архитектура стандартизируется и новым разработчикам легче влиться в проект.

  • Контролируемое переиспользование логики. Каждый компонент архитектуры имеет свое назначение и список зависимостей.

  • Устойчивость к изменениям и рефакторингу. Код можно менять в каждом модуле отдельно, не затрагивая другие.

  • Ориентированность на потребности бизнеса и пользователей. Весь код разбит на бизнес-домены, поэтому просто определить, в какой его части расположена та или иная фича. Это позволяет легко адаптировать элементы проекта под разные задачи.

  • Активное комьюнити. В телеграме есть канал, в котором можно пообщаться с создателями методологии и единомышленниками. Там довольно быстро отвечают на любые вопросы и помогают разобраться в тонкостях FSD. Благодаря этому каналу я уже решил несколько своих кейсов.

Но, конечно, есть и недостатки:

  • Высокий порог входа по сравнению с классическим способом построения архитектуры. Разработчику нужно постоянно думать, как декомпозировать задачу и к какому слою отнести тот или иной модуль.

  • Нельзя начать писать компоненты, а потом отрефакторить код. Вместо этого нужно сразу определить, какие сущности, фичи, виджеты будут использоваться в проекте.

  • Процесс внедрения FSD долгий и дорогой. Придётся создавать специальные линтеры, подходы к код-ревью, следить, чтобы вся команда следовала правилам методологии. Это требует осознанности от каждого человека, потому что если один из команды не станет следовать правилам, то весь проект не удастся поддерживать в рамках методологии.

  • FSD ещё разрабатывается, поэтому в документации описаны не все возможные кейсы. Но этот минус нивелируется активностью сообщества — разработчики быстро помогают решить сложности и описывают в документации разные сложные ситуации.

FSD — это непростая методология. Для работы с ней нужно подготовить команду и дополнительные инструменты. В перспективе внедрение FSD может ускорить и упростить разработку, но необходимость в нём нужно оценивать, исходя из болей и задач конкретной команды разработчиков.

Если вас заинтересовала методология Featured-Sliced Design, дополнительную информацию смотрите по ссылкам на этой странице.

Предыдущая статья: Домашка на лето: что почитать разработчику

Источник: https://habr.com/ru/companies/avito/articles/752536/


Интересные статьи

Интересные статьи

WinAPI (Windows Application Programming Interface) является набором функций и процедур, предоставляемых операционной системой Windows для разработки приложений. В этой статье мы рассмотрим основные пр...
Когда Квебек объявил, что будет рассылать электронные письма с подтверждением вакцинации всем, кто был вакцинирован с помощью прикрепленного QR-кода, у меня немного подкосились колени...
Меня зовут Ростислав Салата, я работаю в киберспортивной организации без малого три года. Пришел в компанию на должность проектировщика интерфейсов, дорос до UX-лида, и в настоящее вр...
В статье описаны наиболее распространенные модели управления, которые используются в российских в компании. В частности дан сравнительный анализ характеристик функциональному и процессному подход...
Сканеры веб-приложений — довольно популярная сегодня категория софта. Есть платные сканеры, есть бесплатные. У каждого из них свой набор параметров и уязвимостей, возможных для обнаружения. Некот...