Сервис развивается: тестируем формат, собираем идеи, улучшаем сервис. Есть идеи?

Написать
Войти
Дайджесты
Слои Feature-Sliced Design и направления импортов

Архитектура на практике: сравнение FSD, Clean и Modular в React-приложении

Эмпирическое исследование шести подходов к организации кодовой базы React измеряет стоимость изменений. Сравнение деления по типам файлов, модулей, чистой архитектуры и трех вариантов Feature-Sliced Design (FSD) помогает выбрать оптимальный баланс между строгостью структуры и скоростью внедрения новых фич.

Архитектура на практике: сравнение FSD, Clean и Modular в React-приложении

Введение: проблема выбора структуры в React-приложениях

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

В крупных коммерческих проектах выбор архитектурного подхода напрямую влияет на скорость разработки, простоту онбординга новых сотрудников и количество багов, возникающих при добавлении новых функций. Исторически сложилось несколько подходов: от простейшего разделения по типам файлов до сложной многослойной методологии Feature-Sliced Design (FSD) и чистой архитектуры (Clean Architecture).

До недавнего времени выбор между этими подходами строился на личных предпочтениях архитекторов и субъективных статьях. Ситуацию изменило новое научное исследование, в котором авторы провели эмпирическое сравнение шести различных архитектурных шаблонов для React, измерив стоимость внесения изменений на реальных сценариях.

Шесть подходов к организации кода

В рамках исследования были подробно изучены и протестированы следующие шесть архитектурных структур:

  1. Folder-by-Type (Разделение по типам). Классическая структура первых React-приложений. Весь код группируется по техническому назначению файлов: папки components/, hooks/, utils/, pages/, services/. Компоненты лежат в одном место, бизнес-логика — в другом.
  2. Modular Architecture (Модульный подход). Код группируется вокруг бизнес-фич или страниц. Проект делится на автономные модули (например, modules/auth, modules/dashboard, modules/catalog). Каждый модуль содержит свои компоненты, хуки и стили.
  3. Clean Architecture (Чистая архитектура). Подход, перенесенный из backend-разработки. Код разделен на три независимых слоя: слой домена (domain — бизнес-правила и сущности), слой данных (data — работа с API и локальным хранилищем) и слой представления (presentation — UI-компоненты React и состояние).
  4. FSD - Flat (Плоский Feature-Sliced Design). Упрощенный вариант методологии FSD. Проект делится на слои (features/, entities/, shared/), но внутри них нет жестких ограничений на вложенность и типы сегментов, что снижает уровень бойлерплейта (шаблонного кода).
  5. FSD - Standard (Стандартный Feature-Sliced Design). Полноценное внедрение методологии. Проект разделен на строго определенные слои (app, pages, features, entities, shared), каждый из которых состоит из слайсов (конкретных бизнес-фич) и сегментов (ui, model, api, lib).
  6. FSD - Strict (Строгий Feature-Sliced Design). Стандартный подход FSD, дополненный строгими правилами импорта. Любые импорты между слайсами должны проходить исключительно через публичные точки входа (index.ts). Нарушения жестко контролируются правилами линтера ESLint.

Методология исследования: симуляция запросов на изменения

Чтобы объективно сравнить эти подходы, исследователи создали эталонное приложение и реализовали его структуру в шести вариантах. Затем они смоделировали набор типичных запросов на изменения (Change Requests, CR) — от простых (добавление нового поля в форму или изменение цвета кнопки) до сложных архитектурных доработок (подключение новой платежной системы, изменение логики аутентификации, кэширование сетевых запросов).

Для каждого архитектурного шаблона при выполнении CR измерялись следующие параметры:

  • Change Locality (Локальность изменений). Метрика показывает, насколько «размазаны» изменения по проекту. Она вычисляется как количество папок и файлов, которые пришлось затронуть при реализации задачи. Чем меньше показатель, тем выше связность (cohesion) и тем легче поддерживать код.
  • Code Size / Boilerplate (Размер кода и шаблонность). Общее количество файлов, строк кода и файлов индексации, необходимых для функционирования архитектуры.
  • Import Coupling (Связанность по импортам). Сложность графа зависимостей между файлами, наличие циклических импортов.

Результаты сравнения: метрики и выводы

1. Локальность изменений и сопровождаемость

Абсолютным лидером по локальности изменений стали стандартный и строгий варианты Feature-Sliced Design. Благодаря разделению кода на автономные слайсы, подавляющее большинство задач по добавлению фич решалось в пределах одного слайса. Разработчику не нужно прыгать по всему проекту: логика, стили, типы и API конкретной фичи находятся в одной папке.

Худший результат показал подход Folder-by-Type. Простая задача по изменению логики авторизации заставила исследователей изменить файлы в папках components/auth, hooks/useAuth, services/api и pages/login. Это повышает риск забыть обновить импорт или сломать соседний компонент.

2. Объем кода и бойлерплейт

Обратной стороной высокой локальности FSD и Чистой архитектуры является колоссальный объем шаблонного кода. В FSD - Strict количество файлов увеличилось более чем на 40% по сравнению с Folder-by-Type. Это связано с необходимостью создавать файлы index.ts (Public API) для каждого слайса и сегмента, чтобы излировать внутреннюю реализацию.

Clean Architecture также продемонстрировала избыточность: разработчикам приходится писать функции-мапперы для конвертации моделей данных из слоя data в слой domain, а затем в UI-модели слоя presentation.

3. Сложность связей и риски рефакторинга

Внедрение FSD - Strict с ESLint-правилами полностью ликвидировало циклические зависимости и хаотичные импорты. Архитектура приложения стала прозрачной. Однако рефакторинг в такой системе стал гораздо дороже. Если бизнес-требования меняются и функционал нужно перенести из сущности (Entity) в фичу (Feature), разработчику приходится переписывать множество публичных точек экспорта и обновлять пути импорта по всему проекту.

Modular Architecture показала наиболее сбалансированные результаты для средних проектов. Она обеспечивает хорошую локальность изменений (код сгруппирован по модулям), но не требует создания десятков файлов-посредников и сложных правил импорта, как в FSD.

Анализ сильных и слабых сторон архитектур

  • Folder-by-Type. Идеально подходит для небольших проектов, хакатонов и прототипов (MVP). Имеет минимальный порог входа и полное отсутствие бойлерплейта. На крупных проектах превращается в «спагетти-код» с запутанным графом зависимостей.
  • Modular Architecture. Оптимальный выбор для большинства команд среднего размера. Логика фич сгруппирована, структуру легко понять без чтения многостраничных гайдлайнов. Слабое место — риск размывания границ модулей со временем, если нет автоматического контроля импортов.
  • Clean Architecture. Хорошо работает в приложениях со сложной математической или бизнес-логикой на клиенте, которая живет независимо от UI (например, графические редакторы или сложные финансовые калькуляторы). Для обычных CRUD-приложений этот подход избыточен и приводит к написанию сотен строк транзитного кода.
  • FSD (Standard / Strict). Лучшее решение для крупных долгоживущих корпоративных приложений с десятками разработчиков. Обеспечивает строгий порядок, независимость команд и защиту от архитектурной деградации. Главные минусы — высокий порог входа, сложность проектирования связей на старте и обилие файлов-пустышек для Public API.

Рекомендации по выбору структуры

На основе эмпирических данных исследователи сформулировали практические рекомендации по выбору архитектуры:

  1. Если вы создаете малый проект или MVP силами 1–2 разработчиков, используйте классический Folder-by-Type или простой Modular. Это сбережет время и избавит от написания лишнего кода.
  2. Для средних проектов (3–10 разработчиков, планируемый срок жизни от года) оптимальным выбором станет Modular Architecture. Она структурирует код, сохраняя высокую скорость поставки фич.
  3. Для крупных enterprise-приложений (множество продуктовых команд, сотни компонентов) настоятельно рекомендуется внедрять Feature-Sliced Design. Накладные расходы на бойлерплейт и проектирование окупятся простотой поддержки, высокой локальностью изменений и защитой от архитектурного хаоса.