![](https://habrastorage.org/getpro/habr/upload_files/e71/a86/a1e/e71a86a1e18d76ebd70a76fdbe857d2e.jpg)
Все мы знаем про, или слышали про практики и паттерны проектирования SOLID, GRASP, MVC, MV** и даже применяем их с переменным успехом, стараясь нащупать эффективный подход к построению приложений. Но это лишь приводит к разнообразию реализаций наших приложений и частей функционала.
И поэтому я уже долгое время пытаюсь понять по каким правилам должно строиться фронтенд приложение чтобы оно удовлетворяло следующим критериям:
легкое расширение функционала приложения;
безболезненное внесение изменений в существующий функционал;
унифицированная структура приложения;
быстрый onboarding новых разработчиков на проект;
понятный и прозрачный код;
всегда понятно где в структуре файлов расположить ту или иную функциональность.
Какие у нас есть варианты?
«Организация файловой структуры это все что нам нужно»
Каждый лид или сеньор сами для себя выбирают варианты компоновки структуры приложения и выделения сущностей приложения. По итогу каждая система становится уникальной и неповторимой. И для того, чтобы разобраться в ней, нужны время и усилия, которые нужно будет тратить каждый раз при смене проекта. Плюс никто не отменял "бас фактор".
Существует большое кол-во статей, описывающих «оптимальные», по мению авторов, варианты таких подходов. Пример.
Но это, в основном, про структуру файлов и частные случаи использования какого-то функционала. Такой подход только частично унифицирует структуру приложения, но этого мало для того, чтобы называться архитектурой. Может есть что-то лучше?
Domain Driven Design
![](https://habrastorage.org/getpro/habr/upload_files/7ad/a56/66a/7ada5666a411c6419bf9a5d6ea0d9795.png)
Много умных дядек, таких как Мартин Фаулер и дядюшка Боб, написали много статей про него. На бэкенде в больших и сложных проектах он неплохо себя зарекомендовал. Но есть и много изъянов: туча абстракций, для простых действий нужно писать много кода, ну и разобраться, как готовить DDD та еще задача.
Есть примеры как готовить это на фронте, но, как видно, проблемы никуда не уходят и кол-во абстракций удручают. Простой onboarding тут невозможен, без прочтения "The Big Blue Book" и пары недель общения с ментором.
Есть переосмысленные подходы к архитектуре, которые больше похожи на правду и наверняка могут где-то успешно применены.
Основательная статья от Кхалила Стеммлера о возможной архитектуре клиентских приложений частично полагается на DDD подход, но при этом сильно его упрощает, освобождая нас от ненужных абстракций и смещая понятия в сторону фронт приложений.
![](https://habrastorage.org/getpro/habr/upload_files/cb7/147/9c5/cb71479c504de666b4df8e279818e5c4.png)
Но бизнес логика в таких приложениях немного размывается и подход больше сфокусирован на функциональных слоях приложения, что отдаляет нас от требования к прозрачному коду и явной бизнес логики.
Джимми Богарт в своей статье пишет что DDD подход не совершенен и избыточен, и, как следствие, он предлагает переработанный подход vertical slices. И это отличный подход, о котором стоит почитать отдельно. Эта идея довольно простая и мы можем адаптировать ее к фронтенд приложениям.
![](https://habrastorage.org/getpro/habr/upload_files/89d/d7f/3f6/89dd7f3f60e472bd467d5feeb737fa7d.png)
Если DDD не удалось применить для наших нужд, то можно попробовать построить его на более общих правилах, которые предоставляет нам "Clear architecture", ведь DDD основывается именно на них.
Clear architecture
![](https://habrastorage.org/getpro/habr/upload_files/a99/9f8/dd4/a999f8dd401afd04bcfef3687e785d2a.png)
Также есть попытки следовать всем постулатам чистой архитектуры и абстрагироваться от представления совсем. В этом случае мы сможем подменять view на любой фреймворк или вообще отказаться от его использования. Интересный подход и в некоторых случаях вполне обоснован и может оказаться отличным решением. Самый частый кейс, это использование одной и той же логики в браузере и на мобильном приложении.
Подробнее об этом можно почитать тут.
![](https://habrastorage.org/getpro/habr/upload_files/e94/96d/5e4/e9496d5e4a43b43cef64bcd5e63fadc9.png)
Разработчики Flutter тоже столкнулись с проблемой сложности переиспользования логики между различными представлениями, и предложили подход - Business Logic Component (BLoC). Он позволяет снизить нагрузку на компоненты пользовательского интерфейса, отделив от них бизнес-логику.
Тут пример одной из реализаций BLoC в React.
Вроде неплохо, но все же есть много вопросов. И почти нет сообщества, которое бы могло помочь с возникающими вопросами.
FSD - Feature Sliced Design
И недавно для меня стало открытием методология FSD - Feature Sliced Design. На мой взгляд лучшем решением будет обратить внимание именно на эту методологию.
![](https://habrastorage.org/getpro/habr/upload_files/e62/4a0/32d/e624a032de6baddc9fbc2fe9990b39bc.png)
Методология не привязана к конкретному стеку технологий и применима к большинству frontend-приложений. Документация содержит примеры реализации на JavaScript + React, но FSD успешно адаптируется и к другим комбинациям инструментов.
Для проектирования архитектуры методология предлагает следующие архитектурные абстракциями на основе которых строиться наше приложение.
![](https://habrastorage.org/getpro/habr/upload_files/f96/5f0/fe8/f965f0fe8bf9ff72fd682696b692bd54.png)
Ниже приведу описание терминов из документации:Layers
Первый уровень абстрагирования - согласно скоупу влияния.
app
- инициализация приложения (init, styles, providers, ...);processes
- бизнес-процессы приложения управляющие страницами (payment, auth, ...);pages
- страницы приложения (user-page, ...);features
- части функциональности приложения (auth-by-oauth, ...);entities
- бизнес-сущности (viewer, order, ...);shared
- переиспользуемый инфраструктурный код (UIKit, libs, API, ...).
Slices
Второй уровень абстрагирования - согласно бизнес-домену.
Правила, по которым код разделяется на слайсы, зависят от конкретного проекта и его бизнес-правил и не определяются методологией
Segments
Третий уровень абстрагирования - согласно назначению в реализации.
ui
- UI-представление модуля (components, widgets, canvas, ...);model
- бизнес-логика модуля (store, effects/actions, hooks/contracts, ...);lib
- вспомогательные библиотеки;api
- логика взаимодействия с API;config
- модуль конфигурации приложения и его окружения.
Ниже приведу пример описания фичи авторизации.
# Сегменты могут быть как файлами, так и директориями
|
├── features/auth # Layer: Бизнес-фичи
| | # Slice Group: Структурная группа "Авторизация пользователя"
| ├── by-phone/ # Slice: Фича "Авторизация по телефону"
| | ├── ui/ # Segment: UI-логика (компоненты)
| | ├── lib/ # Segment: Инфраструктурная-логика (helpers/utils)
| | ├── model/ # Segment: Бизнес-логика
| | └── index.ts # [Декларация Public API]
| |
| ├── by-oauth/ # Slice: Фича "Авторизация по внешнему ресурсу"
| ...
Помимо унификации структуры, мы получаем наглядную бизнес логику, отличное описание слоев приложения с примерами на популярных ЯП. Также есть ответы на вопросы о расположении функционала и понятные правила уменьшения зависимостей в коде.
Эта методология только развивается и есть хорошее комьюнити, которое так же как и мы задается вопросами архитектуры фронтенда.
Заключение
У каждого из подходов есть свои плюсы и минусы. Учитывая что каждый проект имеет разный размер, сложность и специфику и цели, то что подойдет многим не факт что подойдет вам. Надеюсь что после прочтения статьи вы откроете для себя что то новое и сможете улучшить ваши собственные проекты.
Также если вам интересно в своем Telegram я время от времени выкладываю интересные находки по фронтенду. И всем чистой архитектуры.