Архитектура фронтенда и какой она должна быть
Published: 2022-06-14 07:18:47

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

И поэтому я уже долгое время пытаюсь понять по каким правилам должно строиться фронтенд приложение чтобы оно удовлетворяло следующим критериям:

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

Какие у нас есть варианты?

## Организация файловой структуры это все что нам нужно

Каждый лид или сеньор сами для себя выбирают варианты компоновки структуры приложения и выделения сущностей приложения. По итогу каждая система становится уникальной и неповторимой. И для того, чтобы разобраться в ней, нужны время и усилия, которые нужно будет тратить каждый раз при смене проекта. Плюс никто не отменял ["бас фактор"](https://ru.wikipedia.org/wiki/%D0%A4%D0%B0%D0%BA%D1%82%D0%BE%D1%80_%D0%B0%D0%B2%D1%82%D0%BE%D0%B1%D1%83%D1%81%D0%B0#:~:text=bus%20factor%2C%20%D0%BB%D0%B8%D0%B1%D0%BE%20truck%20factor,%D1%83%20%D0%BD%D0%B8%D1%85%20%D1%80%D0%B5%D0%B1%D1%91%D0%BD%D0%BA%D0%B0%2C%20%D0%BD%D0%B0%D1%81%D1%82%D1%83%D0%BF%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BD%D0%B5%D1%81%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%BE%D0%B3%D0%BE).

Существует большое кол-во статей, описывающих «оптимальные», по мению авторов, варианты таких подходов. [Пример](https://clck.ru/hnGZh).

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

## Domain Driven Design

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c73q4zjmtdnkdkq6dc59.png)

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

[Есть примеры](https://habr.com/ru/post/654629) как готовить это на фронте, но, как видно, проблемы никуда не уходят и кол-во абстракций удручают. Простой onboarding тут невозможен, без прочтения "[The Big Blue Book](https://www.domainlanguage.com/ddd/blue-book/)" и пары недель общения с ментором.

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

[Основательная статья от Кхалила Стеммлера](https://khalilstemmler.com/articles/client-side-architecture/introduction/) о возможной архитектуре клиентских приложений частично полагается на DDD подход, но при этом сильно его упрощает, освобождая нас от ненужных абстракций и смещая понятия в сторону фронт приложений.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5bcg19cmt6gk549lhh0f.png)

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

Джимми Богарт в [своей статье](https://jimmybogard.com/vertical-slice-architecture/) пишет что DDD подход не совершенен и избыточен, и, как следствие, он предлагает переработанный подход vertical slices. И это отличный подход, о котором стоит почитать отдельно. Эта идея довольно простая и мы можем адаптировать ее к фронтенд приложениям. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9diyl47c5732nvu1aplw.png)

Если DDD не удалось применить для наших нужд, то можно попробовать построить его на более общих правилах, которые предоставляет нам "Clear architecture", ведь DDD основывается именно на них.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ofajo4sqb0ogevyr42rx.png)

Также есть попытки следовать всем постулатам чистой архитектуры и абстрагироваться от представления совсем. В этом случае мы сможем подменять view на любой фреймворк или вообще отказаться от его использования. Интересный подход и в некоторых случаях вполне обоснован и может оказаться отличным решением. Самый частый кейс, это использование одной и той же логики в браузере и на мобильном приложении. Подробнее об этом можно [почитать тут](https://dev.to/xurxodev/moving-away-from-reactjs-and-vuejs-on-front-end-using-clean-architecture-3olk).

Разработчики Flutter тоже столкнулись с проблемой сложности переиспользования логики между различными представлениями, и предложили подход - [Business Logic Component](https://pub.dev/packages/flutter_bloc) (BLoC). Он позволяет снизить нагрузку на компоненты пользовательского интерфейса, отделив от них бизнес-логику.

[Тут пример](https://blog.bitsrc.io/using-bloc-pattern-with-react-cb6fdcfa623b) одной из реализаций BLoC в React. Вроде неплохо, но все же есть много вопросов. И почти нет сообщества, которое бы могло помочь с возникающими вопросами.

## FSD - Feature Sliced Design

И недавно для меня стало открытием методология FSD - Feature Sliced Design. На мой взгляд лучшем решением будет обратить внимание именно на эту методологию. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ops80bfskoj593u8hcmf.png)

[Ссылка на офф сайт](https://feature-sliced.design/).

Методология не привязана к конкретному стеку технологий и применима к большинству frontend-приложений. Документация содержит примеры реализации на JavaScript + React, но FSD успешно адаптируется и к другим комбинациям инструментов.

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z6buflsuc39zfjkfjnwb.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](https://t.me/devreverza) я время от времени выкладываю интересные находки по фронтенду. И всем чистой архитектуры.