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

Мы используем preact/compat, что дает нам доступ к множеству библиотек в экосистеме React, тем самым делая процесс разработки более гибким, сохраняя при этом возможность использовать Preact. Однако у этих самых преимуществ часто есть обратная сторона: например, нет единой методологии для проектов дизайна приложений, как, например, в Angular. Кроме того, огромное количество библиотек затрудняет погружение в проект, а свобода реализации и проектирования ваших идей может привести к загромождению базы кода, что отпугивает разработчиков, особенно новичков.

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

Для нашей команды эти вопросы также актуальны. Чтобы решить эту проблему раз и навсегда, мы приняли методологию Feature-Sliced ​​Design (FSD), которая сейчас активно набирает обороты. Ниже я расскажу о его основных принципах и опишу наш опыт работы с ним. Ой, я забыл представиться. Меня зовут Женя, я фронтенд-разработчик из команды быстрых экспериментов в inDrive. Я расскажу вам, как мы развиваем наши собственные стартапы на основе бизнес-гипотез с помощью FSD.

Методология FSD основана на трех уровнях абстракции:

1. Слои. Этот уровень определяет сферу ответственности уровня и уровень риска изменений. Чем выше уровень, тем выше уровень его ответственности и знаний о других слоях. Чем ниже слой, тем он более абстрактен и чем больше он используется в верхних слоях, следовательно, тем выше опасность, связанная с внесением в него изменений.

2. Срезы. Срезы отражают конкретные функциональные возможности используемой бизнес-логики. Эта методология почти не имеет никакого эффекта на этом уровне; многое зависит от конкретного проекта. По сути, это папки, в которых собраны файлы, реализующие тот или иной модуль.

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

  • api/ — работа с API. Авторы методологии советуют выносить логику API на общий слой, чтобы она не была разбросана по всему проекту.
  • config/ — конфигурация модуля.
  • lib/ — различные служебные функции и вспомогательные библиотеки.
  • model/ — бизнес-логика: хранилище, действия, эффекты, редукторы и т.д.
  • ui/ — отвечает за отображение.

Графическое представление методологии FSD

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

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

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

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

Прежде чем мы рассмотрим каждый уровень отдельно, вот несколько общих советов о том, как реализовать подход FSD:

  1. Все разработчики в команде должны хорошо понимать эту методологию. Все без исключения новые разработчики обязаны внимательно прочитать документацию FSD. В противном случае внедрение методики точно не принесет никакой пользы.
  2. Любые глобальные архитектурные изменения должны обсуждаться всей командой. Время от времени важно анализировать архитектуру на предмет перекрестного импорта и «болевых точек» в кодовой базе. По большому счету, этот совет применим и к любым другим типам архитектуры.
  3. Вам не нужно реализовывать все возможности методологии FSD и использовать все уровни абстракции и типы слоев. Поскольку проекты и опыт разработчиков могут существенно различаться, лучше всего, если желаемый уровень декомпозиции был согласован и определен внутри самой команды. В процессе разработки этот параметр всегда можно подправить, чтобы найти собственный оптимальный баланс между простотой реализации и преимуществами методологии.

Теперь давайте подробно рассмотрим каждый слой, от самого нижнего до самого высокого.

1. Shared — самый абстрактный слой приложения. Он содержит повторно используемые модули, не связанные с бизнес-логикой. Этот уровень является хорошим местом для начала применения методологии FSD. В наших проектах этот каталог разделен на несколько сегментов, некоторые из которых недоступны в FSD:

  • shared/api — работа с API.
  • shared/config — модуль конфигурации приложения и его окружения.
  • shared/hooks — настраиваемые хуки.
  • shared/lib — различные служебные функции и вспомогательные библиотеки.
  • shared/themes — список цветов и тем приложения.
  • shared/ui — компоненты пользовательского интерфейса: Input, Select, Table и т. д.

Самое главное здесь — не путать абстрактные компоненты пользовательского интерфейса с компонентами, реализующими конкретные бизнес-сущности или функции. Например, Select — это компонент Shared/UI, тогда как CitySelect — это функция. При создании модуля необходимо оценить, будут ли бизнес-сущности использоваться в компоненте. Если нет, модуль должен быть назван как можно более абстрактно и помещен в Shared. В противном случае рекомендуется указать в его имени бизнес-сущность или функцию, которую реализует модуль, и поместить ее в слой Entities или Features. Умное, разумное именование играет важную роль в этой методологии.

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

3. Функции — это части функциональности приложения. Это, пожалуй, самый сложный уровень для понимания и определения в этой методологии, потому что само определение «функции» зависит от конкретной области применения и бизнес-требований. Поэтому при переходе на FSD «фичи» стоит реализовывать только в том случае, если вы абсолютно уверены, что это не создаст дополнительных сложностей для разработчиков.

Изначально нашей команде было трудно определить разницу между функциями и сущностями. После нескольких обсуждений мы пришли к соглашению, что фича — это полезная (и желательно единственная) функциональность для пользователя, а сущность — это то, что используется для реализации этой функциональности. Пример: City и Product — это объекты, тогда как SearchByCity и BuyProduct — это функции.

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

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

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

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

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

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

Если проект запускается с нуля на основе FSD, изначально все описанные выше концепции кажутся ненужными и чрезмерно сложными. Я считаю, что новые слои и уровни декомпозиции следует внедрять только тогда, когда команда понимает, что в них есть явная необходимость. В противном случае большое количество слоев может усложнить жизнь разработчикам и запутать их. Плюс сама методология, как было сказано выше, не требует принятия всех подходов.

Эти трудности полностью компенсируются такими преимуществами, как упрощенная адаптация и командная работа, а также единая терминология. Эта методология побуждает разработчиков сосредотачиваться на бизнес-целях и отражать их в коде. Тогда (в идеальном мире, конечно) никому не придется объяснять цель создания того или иного модуля.

Источники:

  1. Официальная документация по методологии FSD.
  2. Отличный отчет одного из соавторов методики.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord . Заинтересованы в хакинге роста? Ознакомьтесь с разделом Схема.