Pull to refresh

Comments 42

Классно! Я уже много лет пишу на чистой архитектуре на реакте. Всегда идеально отрабатывает какой бы специфичный или огромный проект ни был.

А вот со статьёй вы меня опередили, моя только наполовину написана, и она очень пересекается с вашей.

Интересно какой процент разработчиков используют чистую архитектуру в веб-приложениях. У меня есть проблема с подбором разработчиков, большая часть кроме редакса ничего не знают и знать не хотят. Как вы решаете эту проблему?
В любом случае, интересно увидеть Вашу статью. Подчерпнуть что-то новое всегда можно (почему-то так выходит, что чистая архитектура у всех немного своя :)).

«У меня есть проблема с подбором разработчиков, большая часть кроме редакса ничего не знают и знать не хотят.» — честно говоря, я не сильный фанат Redux'a. Если приложение пишет больше, чем 1-2 человека — может начать путаница из-за сваливания состояния. Кто-то где-то что-то отправляет (не дай Бог из UI'я) — и искать это проблематично, все состояние находится в куче. К тому же, Redux особо-то и не отобразишь на UML диаграмме, например. Какой-нибудь Repository\Entity с шаблоном Observer лучше поддается понимаю и все состояние не сваливается в кучу. Это лично мое мнение, но я его избегаю. Аналогичный подход с Redux Saga — UseCase\Repository + View Model на async\await более красиво решают эту проблему и цепочку вызовов видно напрямую.

«Как вы решаете эту проблему?» — только учить. Специалисты стоят довольно дорого и проекты не всегда имеют для них бюджет. Поэтому объяснение + код ревью. Чистая архитектура не сложная вещь (вообще, сложные вещи в разработке с трудом приживаются и тяжело поддерживаются) — поэтому разработчики довольно быстро ее понимают и со временем начинают использовать без проблем.

Ну не знаю…
Пилю средне-большие проекты на react-redux и никаких архитектурных проблем не встречал. Как по мне это overengeenring, т.к. в основном все правила бизнес логики должны быть реализованы на бекенде. А ради валидации формы пилить такой огород классов и связей…
ИМХО на бекенд/native приложения это ложится гораздо лучше.

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

Изначально я перешел на такую архитектуру, потому что логика в UI крайне тяжело поддается тестированию, а UI\ViewModel\Presenter слои начинают становиться God-объектами с дублирующимся кодом.

«ИМХО на бекенд/native приложения это ложится гораздо лучше.» — вообще, эту архитектуру придумали изначально для сложных бекенд приложений :). Поэтому часто для мелких фрондент проектов она избыточна — но, опять же, зависит от проекта. Как писать большой проект без чего-то подобного, оставляя его поддерживаемым, я не представляю (а ведь кто-то и fetch из onClick делает...)

А в чём собственно сложность тестирования? Если мы например берём redux, то там всё достаточно просто. Это ж просто чистые функции.


И ещё интересно, где в такой архитектуре хранилище? В бекендах хранилищем обычно выступает БД. Вам же всяко информацию где-то надо хранить (надеюсь не предполагается этого делать в моделях). И тут приходим к тому что всё равно нужно что-то типа redux (единый источник правды), иначе будут проблемы с неконсистеными состояниями и всем тем что react сообщество успешно побороло 4+ лет назад


Мне кажется, даже размер команды, и размер приложения это ещё не повод выбирать именно чистую архитектуру. Как вариант, приложение можно разбить на несколько разных модулей (lerna/monorepo), контролируя тем самым их размер. И это будет тоже довольно просто поддерживать и расширять.

«А в чём собственно сложность тестирования?» — я имел ввиду не только передачу состояния, а тестирования для проекта в целом (включая передачу данных, обработку данных, изменение View в зависимости от изменения данных и т.д.).

«И ещё интересно, где в такой архитектуре хранилище?» — слой Repository в 95% случаев. И тем, кому нужна авторизация — дергают авторизацию по интерфейсу.

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

«Как вариант, приложение можно разбить на несколько разных модулей (lerna/monorepo), контролируя тем самым их размер.» — возможно. Скажу честно, я таким не пользовался, а мой подход с чистой архитектурой лишь один из многих. Как я сказал, я лишь описываю свой опыт и лично я не люблю Redux, потому что для меня и моей команды было проще работать, используя другой подход. Но! Redux зарекомендовал себя и ничего против его использования я не имею. Так что я не отрицаю другие подходы, хотя и использую приведенную выше архитектуру, потому что она оказался самым удобным для нас решением.
Сложность проектирования архитектуры UI не в том, чтоб написать MVP со всеми рюшечками на каждую форму. А чтоб иметь возможность выкинуть произвольное количество рюшечек (бойлерплейта) вплоть до 100%, сообразно сложности той или иной формы.

То, что вы написали — это прекрасно и часто абсолютно необходимо для очень сложных UI, и лютый overengineering для простых вещей, типа формы о двух инпутах.

Плюс, если отойти чисто от архитектуры и перейти к вашему коду — мне, например, страшно не нравятся ваши ViewModelImpl. Там кругом мутабельность и неконсистентный стейт (дёрнули validate() — в модели одно, не дёрнули — другое), разбираться в этом всём при росте кода — будет убийственно. Если у вас в модели нет single source of truth — ни к чему хорошему это никогда не ведет.
«То, что вы написали — это прекрасно и часто абсолютно необходимо для очень сложных UI, и лютый overengineering для простых вещей, типа формы о двух инпутах.» — несомненно. В этом и суть.

«и лютый overengineering для простых вещей, типа формы о двух инпутах.» — разумеется, пример сильно надуманный, чтобы показать использование. Но! Если предположить, что этот код будет сильно меняться, а также писаться большим количеством людей — мы можем начать покрывать тестами на разных слоях, и избежать будущих проблем. Вообще, архитектуры\тестирование приобретают большую силу, именно когда проект пишется большим количеством людей на протяжении 1+ лет. Разработчики как раз начинают забывать свой код...

В общем, it depends. Но пример и правда с overengineering'ом, но только для того, чтобы объяснить архитектуру на примере.

«Плюс, если отойти чисто от архитектуры и перейти к вашему коду — мне, например, страшно не нравятся ваши ViewModelImpl.» — разумеется, чем больше код и сложнее логика, тем сложнее его читать — но глобальных проблем с этим я раньше не замечал. God-объектов в View Model я избегаю за счет Use Case'ов и внутреннего слоя. Можете привести пример, как бы Вы это реализовали?

А что на *Impl ответите? Я бэкендщик, но иногда приходится писать и на фронте, описанный вами подход много ближе ложится в привычные бэкенд подходы, чем то, что продвигает редакс.
Но вот этот момент и *Impl мне кажется несколько оверинжиниринговым.

*Impl — чтобы во время тестирования подсовывать классам интерфейсы. Редко эти *Impl меняются на что-то другое, поэтому подход исключительно ради удобства тестирования. Тем более, интерфейсы с одной реализацией они используются не везде — а только в ViewModel\Repository.

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

Опять же, как я написал выше, "основную силу архитектуры\тестирование приобретают в больших проектах с несколькими разработчиками, где нужно понимать и изменять чужой код". Если вы говорите, что это оверинжениринг для чего-то относительно маленького и даже среднего — я с Вами абсолютно согласен
Пардон, я не проснулся толком и не прочитал, что у вас валидация private и вызывается из самой ViewModelImpl. Так — нормально, да.

Ну, с тем замечанием, что вся ViewModel — это первейший кандидат на вылет при упрощении кода.
Как обычно, сами себе проблем навыдумывают и потом пытаются их решать.

Весь фронтенд это:
— Слой view
— Слой состояния
— Слой бизнес логики

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

P.S. посмотрите в сторону MobX, уверен от этого ваша жизнь станет гораздо проще. То, как вы используете локальный стейт компонентов и то, как из вне им манипулируете используя всякие подписки и колбэки, это конечно жесть.
UFO just landed and posted this here

action всё же лучше не забывать, потому что здесь, например, у вас семантика поменялась — с action неявный notifyListeners будет вызван после завершения метода (как и у автора), а у вас — дважды, после каждого присваивания в observable, так что утекает неконсистентный стейт.


  public onSignedOut(): void {
    this.isAuthorized = false;
    this.authToken = '';
    //this.notifyListeners();
  }

А в целом да, с mobx (и mobx-state-tree) подход получается очень похожий на описанный автором. Отдельно — store с моделями, которые те же entities, зависящие от них контроллёры частей приложения, далее — зависящие от них реакт-контейнеры, которые рендерят тупые реакт-компоненты. API и storage так же можно вынести за интерфейсы и инжектить.

Есть один не хитрый прием, уже давно им пользуюсь для того, чтобы автоматом всегда все изменения батчились и не нужно использовать action и runInAction.
import { configure } from 'mobx';

// Configure MobX to auto batch all sync mutations without using action/runInAction
setTimeout(() => {
    configure({
        reactionScheduler: (f) => {
            setTimeout(f, 1);
        },
    });
}, 1);

P.S. В некоторых кейсах, если это сразу синхронно объявить, то реакции могут барахлить, поэтому нужен setTimeout.
Проверка в действии — codesandbox.io/s/sad-turing-7vkpz?file=/src/index.js

Хм, интересный хак. Но например с тем же реактом есть определённый плюс в синхронной отрисовке — можно поменять стейт в методе компонента через экшены и потом при необходимости сразу ручками лезть в dom, без всяких заморочек с ожиданием апдейта компонента. Да и явное, как известно, лучше неявного :)
Но за трюк спасибо, может и пригодится как-нибудь.

Вообще не понял в чем смысл того, что вы описали и для чего всё это?

Допустим, у вас есть какой-то достаточно сложный компонент (например, какой-то список), который изменяет стейт, а изменение стейта вновь изменяет этот компонент (добавляет элементы в верх списка). И вы хотите, например, запоминать позицию скролла.


addElements() {
  const scrollH = this.el.current.scrollHeight // старая высота элемента со списком
  this.props.store.addElementsToTop() //action в сторе, который триггерит ререндер текущего компонента
  this.el.current.scrollTop += this.el.current.scrollHeight - scrollH  //прокручиваем список на старую позицию
}

Если у вас честный action, сразу после его вызова (2 строчка) компонент (если он observer, конечно) синхронно перерисуется и в третьей строчке scrollHeight будет уже актуальным. С вашим же трюком на третьей строчке компонент будет ещё не перерисован (потому что observer внутри — это та же реакция).

Для этих дел есть жизненный цикл компонента, componentDidUpdate или useEffect внутри которых выполняем:
this.el.current.scrollTop += this.el.current.scrollHeight - this.lastScrollH;

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

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

В реакте давно добавили свой батчинг рендера, проверьте, актуальные версии реакта и mobx по крайней мере так не работают)
Вот посмотрите codesandbox.io/s/sweet-kowalevski-wursj

Да вот сидел и твердил себе"не забыть проставить, когда их переименовывать буду", но решил не переименовывать, хотя и режет глаз on*

Увидел Ваши пулл реквесты, спасибо за них. Просмотрел код и, если в слой presentation добавить MobX — действительно, код становиться понятнее (но, опять же, плюс The Clean Architecture — MobX можно положить только в один слой :), не трогая остальные. В Entities я его добавлять бы не стал)

На след. выходных я обязательно в нем разберусь. Спасибо, что потратили время и показали свое видение

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

И Ваш код с MobX, как по мне, очень даже сильно дополнит архитектуру.

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

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

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

Честно говоря, я ни разу не встречал подобных решений на фронте. Здесь разработка делится по фичам/страницам/экранам и для каждой ведётся в одну каску, максимум две — CSS и JS. По аналогии, это больше напоминает пельмени: тесто, фарш. Поэтому ритуалы с дополнительными слоями внутри, как в тортах, кажутся несколько избыточными.

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

Скорее они стремятся друг к другу.


Честно говоря, я ни разу не встречал подобных решений на фронте. Здесь разработка делится по фичам/страницам/экранам и для каждой ведётся в одну каску, максимум две — CSS и JS

Если фронтов несколько (хотя бы пользовательское приложение и админка), то вполне может быть что в три и более "каски": связь с бэком в том или ином виде, расшариваемая между фронтами и два UI.

Спасибо за статью, было интересно.
Какое же огромное количество подходов крутится вокруг разработки на React.
Я не видел нигде полного руководства о том, как стоит строить гибкую архитектуру в React. Эти знания раздроблены по разным местам и все делают этот как хотят. И это очень хорошо, что автор поднял этот вопрос. Если кто-то знает такие ресурсы скиньте пожалуйста в комментарий.

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

Он слишком сильно завязан на ООП. React же больше не об ООП. Концепция обработки логики с помощью redux + saga куда более близка к духу React. Та же иммутабельность, те же редьюсеры и чистые функции. Если хотите ООП используйте идею сервисов из Angular и MobX.

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

Я переписал это приложение, сделав ближе к тому, что я считаю чистой архитектурой, но при этом оставил точно такое же поведение. Дополнительных библиотек не использовал, логику вынес в сервис. Вот, что у меня получилось:
https://github.com/VladislavMurashchenko/clean-architecture-react-typescript/
«Создается огромное количество абстракций которые создаются не потому, что они нужны и улучшают читаемость, а потому, что так требует архитектура.» — да, проект надуманный. Но, опять же, чем больше появляется логики — тем большее ее смысл.

«Я больших проектах я рекомендую Атомарный дизайн» — можете продублировать ссылку? К сожалению, не открывается

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

Проблема таких статей всегда в том что плохо когда удается показать сложные подходы на простых примерах. Это как собирать лунный велосипед, а используемые подходы демонстрировать на обычном. Оно будет смотреться очень нелепо, переусложненно а иногда и забавно. Оценят демонстрируемые решения только те кто уже занимался похожими разработками. В то-же время выложить целый проект в open-source для демонстрации подхода очень затруднительно.

Почувствовал себя в 2005. Лютый over engineering. Ну да бог с ним. Почему у вас:


  • нет автоматической реактивности. Вы всё делаете руками. Все подписки, все привязки, все уведомления. Как в каменном веке. Любая механическая ошибка и сиди дебаж что и почему сломалось
  • почти нет декларативности (кроме типов). Уже буквально любой современный подход предполагает либо указание зависимостей (react), либо детектирование зависимостей от их использования (vue, mobX, knockout). Это сильно упрощает жизнь и даёт большие возможности в оптимизациях производительности.
  • зачем вам React? Если вы застряли в 2005г и пишете в духе Backbone, то возьмите легковесный строковый шаблонизатор, зачем тащить целый React туда, где вы его на 3% используете. React + React.dom отнюдь не невесомые. Это очень большие и довольно сложные кодовые базы. Они решают те задачи, которые вы на них не накладываете.
  • так много бойлерплейта. Вы даже redux переплюнули в этом деле

По сути вы добились того, что у вас можно изъять React из приложения и заменить его чем-нибудь другим. Сделали вы это за счёт того, что используете React как dump components renderer. Из пушки по воробьям. Зачем? Ну да, теперь его можно выкинуть. Дак выкинули бы с самого начала тогда. Хорошо хоть не Angular. Вместо привязки к, о боже, чужим фреймворкам, у вас теперь большая привязка именно к вашему собственному фреймворку. Не то чтобы это было плохо, но записать в преимущества это будет сложно.


Из позитивных моментов:


  • У вас много изолированных друг от друга слоёв. Это правда про clean code

Из негатива:


  • Вы перестарались, и цена фичи выросла раза в 4. Даже в Redux меньше "капусты" и копипасты
  • Высокий уровень входа для новичков (в меру высокий)
  • Слишком много ручной работы, а следовательно высокая цена кода и большое пространство для формирования багов

Добавьте хотя бы какой-нибудь dependency tracking и готовый (да пусть даже самописный) observable. Не пишите notify руками. Пожалейте ваших коллег.


Ещё рекомендую, если вам таки нужен React, именно в компонентах и писать ViewModel. Он собственно для этого и создан. В качестве разделения сложной логики (когда надо) можно исопльзовать кастомные хуки-зонтики. Их же в итоге можно и тестировать изолированно. Ну и реактивность из коробки.


P.S. Прошу не воспринимать близко к сердцу. Просто сложилось впечатление что про clean code и паттерны вы читали, а про современные подходы во фронтенде нет. В итоге на слои вы нарезали, но удобного и практичного решения в духе времени не получилось. Примерно так и писали во времена Backbone.js

Спасибо за комментарий!

«Вы перестарались, и цена фичи выросла раза в 4. Даже в Redux меньше „капусты“ и копипасты» — опять же, пример надуманный и здесь действительно много overengeneering'a.

«Высокий уровень входа для новичков (в меру высокий)» — не согласен. Вопрос изучения — максимум пару дней + поправка на общий опыт. В сравнении с тем, что пишут вообще без какого-либо подхода — я считаю, что архитектура выше большой шаг вперед. Собственно, и статью я написал потому, что не увидел других общепринятых подходов. Или только с акцентом на библиотеку, или вообще никак.

«Слишком много ручной работы, а следовательно высокая цена кода и большое пространство для формирования багов» — это тема для второй статьи. Собственно, во второй статье будет добавлен MobX и часть ручной работы отпадет.

Ключевая идея статьи в том, что серебряной пули нет — но есть такая, как описаны выше. И свои задачи она решает может не всегда идеально, но решает и в большинстве своем закрывает свои задачи.

Если у Вас будет время, можете рассказать, как бы Вы изменили архитектуру выше? Может просто созвониться и обсудить\пообщаться в Telegram. Я несомненно ищу пути улучшения подхода, который использую и статья — один из способов его улучшить в какой-то мере
Если у Вас будет время, можете рассказать, как бы Вы изменили архитектуру выше?

  1. Добавил бы observables (можно и MobX) и постарался бы сделать декларативным почти всё что получается с пользой для дела сделать декларативным
  2. Как можно больше бы всё унифицировал и уделил большое внимание тому, чтобы не писать так много копипасты
  3. Вынес бы VM в React компоненты (он для этого и создан). Ну или хотя бы в MobX слой. Да это создаёт большую привязку к фреймворкам\либам, зато сильно упрощает разработку (ура!).
  4. Продумал бы возможность частичной подписки на данные, а не сразу на всё разом

Затем попробовал бы это в деле с годик. По ходу пьесы наткнулся бы на 100500 неудобных мелочей и не только. Сел бы и подумал как правильно решить эти проблемы. Уже зная в мелочах в чём эти проблемы. И снова по кругу. Придумал идею, попробовал на мелком модуле. Если зашло — используем. Если нет — ищем дальше...


Но всегда держал бы в голове, что clean code это не догмы. Это советы, руководство к действию. В первую очередь код должен решать поставленные перед ним задачи. Если какой-то pattern или правило создаёт много проблем, то надо сесть и подумать что не так. И решить — это правило не для нас\мы делает что-то не так.


Руководствуясь "правильными принципами" легко загнать даже мелкую кодовую базу в такой кромешный кровавый ынтерпрайз, что в нём дыхнуть сложно будет без уведомления 5 инстанции, изменения 5 интерфейсов, и 25 тестов. Любой инструмент, будь то какая норма, или правило, или библиотека, должен приносить больше пользы, чем страданий.

UFO just landed and posted this here

MobX по идее и обеспечивает частичную подписку на данные.

Как observables сочетается с декларативностью. observables — это её часть или ещё нет?

Ну кодовая база же не состоит только из observable примитивов. Где-то есть какие-нибудь конфиги, схемы и пр… Сделать некую структуру\схему, которая, путём запуска её в неком интерпретаторе, избавляет от рутины и всё делает однообразным образом. В первую очередь я имел ввиду это.


Во вторую, в моём понимании, есть что-то промежуточное между декларативным и императивным подходом. Не знаю как это правильнее назвать. Ну скажем декларирование зависимостей в observables или автоматическое их выявление мне кажется более декларативным, нежели руками через if-ы. Тот же useEffect мне кажется более декларативным, нежели груда if-ов в componentWillReceiveProps. Как это по уму обозвать я не знаю.


Совет №4 тоже сомнителен, хотя в текущих реалиях ($mol пока не в них) безальтернативен

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

Спасибо за статью!

Я сам стремлюсь к балансу простоты, масштабируемости и уменьшению бойлерплейта. Но, использую Flux-подобный подход. Возможно, вам будет интересен мой пример:
github.com/sergeysibara/mobx-react-4-tier-architecture
codesandbox.io/s/mobx-react-lite-4-tier-architecture-ue2v1

Файловая структура по большей части by features.
Код разделен на 4 основных слоя:
  • view — компоненты
  • store — слой глобальных данных. Для каждой feature свой стор
  • actions — middleware слой для побочных эффектов.
  • api — слой взаимодействия с сервером

view взаимодействуют только со сторами и actions. Компоненты могут подписываться на сторы, но не могут их изменять. Изменять стор могут только actions.

стор не знает ни о каком слое, ни о других сторах. К нему за данными могут обращаться компоненты и actions. Ну и подписаться на его изменения.
В сторе хранятся только глобальные данные и getter-ы/setter-ы для них. Плюс логика для преобразования этих данных (например, фильтрация). Никакой сторонней бизнес-логики, не относящейся к работе с этими данными, здесь быть не должно.

actions вызывают api и обрабатывают полученные данные, а также обновляют сторы. Могут как считывать, так и изменять сторы. Различные сопутствующие сайд эффекты также в этом слое.

api ничего не знает о других слоях. Единственные назначения – взаимодействие с сервером и преобразование данных в нужный формат перед отправкой и после получения.

В моем примере классы сторов, api, actions можно наследовать и переопределять или использовать свои, если базовые не подходят. В базовые классы я выношу стандартный общий функционал для REST (получить отфильтрованный и отсортированный список, получить один элемент, создать новый элемент, изменить существующий, удалить элемент).
При добавлении новой страницы или группы страниц, относящиеся к одной feature, в основном изменения будут в пределах одной папки, как в моем примере: src/pages/todos. В ней находятся унаследованные стор, api, actions и компоненты, относящиеся только к функционалу todos.
Спасибо за комментарий!
В ближайшие недели хочу разобраться во всех подходах, которые мне посоветовали\дополнили и дополнить свою архитектуру (на очереди — MobX).

Обязательно посмотрю Ваш репозиторий, не удаляйте его в ближайшее время, пожалуйста :)
Не планирую пока-что удалять) К тому-же в другой ветке в нем немного другой вариант пробую. Да и был бы рад отзывам, замечаниям.
На мой взгляд здесь слишком много кода. Цель любой архитектуры уменьшить количество ошибок и облегчить разработку большой команде.

Но чем больше кода и элементов в системе, тем сложнее её разрабатывать и поддерживать, ведь появляется всё больше мест для совершения ошибок.

Через 5 лет мучений на разных СТМ и подходах с реактом я пришел к Effector, и три года искал способы писать код в большой команде. Оказалось, что его модели можно класть рядом с VM-компонентом не обременяя себя проблемами огромной кодовой базы. Каждый разработчик у нас в команде думает лишь о двух вещах: как реализовать UI без привязки к логике и как реализовать логику не думая о UI. При этом никто не хочет думать об особенностях CleanArchitecture, мы лишь думаем о данных и событиях, грубо говоря о потоках данных.

Можем пообщаться в Telegram и обсудить подходы, которые мы используем в production. Мне несколько неловко писать огромные статьи на хабр.
Через 5 лет мучений я пришел к Effector

Серьезно?)) Effector?))
Сочувствую конечно.
А про MobX вы похоже не слышали да?
Sign up to leave a comment.

Articles