СТАТЬЯ

Архитектура приложений Flux и React

Из React in Action Марка Томаса.
________________________________________________________________________________

Скидка 37% на React in Action.
Просто введите код fccthomas в поле для кода скидки при оформлении заказа на manning.com.
______________________________________________________________________________

Эта статья посвящена архитектуре приложений Flux и ее возможностям.

Архитектура приложения Flux

Современные приложения должны делать больше, чем когда-либо прежде, и, соответственно, они более сложны — как внутри, так и снаружи. Разработчики уже давно знают о беспорядке, который может быть сделан из сложного приложения, которое растет без согласованных шаблонов проектирования. Кодовые базы спагетти не только не доставляют удовольствия, но и замедляют работу разработчиков и бизнес-подразделений. Помните, когда вы в последний раз работали с большой кодовой базой, полной одноразовых решений и плагинов jQuery? Наверное, это было не весело. Чтобы бороться с неорганизованностью, разработчики разработали такие парадигмы, как MVC (Model View Controller), чтобы организовать функциональность приложения и направлять разработку. Flux (и, соответственно, Redux) — это работа в том же духе, которая помогает вам справляться с возросшей сложностью приложения.

Не беспокойтесь, если вы не знакомы с парадигмой MVC; мы не будем тратить на это много времени. Но прежде чем мы поговорим о Flux и Redux, было бы полезно кратко обсудить их для сравнения. Если вам интересно узнать больше о MVC, у Джеффа Этвуда есть несколько полезных мыслей по адресу https://blog.codinghorror.com/understanding-model-view-controller/, а также множество других ресурсов, доступных в Интернете.

  • Модель: данные для вашего приложения. Обычно это существительное, например, «Пользователь», «Учетная запись» или «Публикация». Ваша модель должна иметь основные методы для управления связанными данными. В самом абстрактном смысле модель представляет необработанные данные или знания. Здесь данные пересекаются с кодом нашего приложения. Например, в базе данных может храниться несколько свойств, таких как «accessScopes» или «аутентифицировано». Но модель может использовать эти данные для метода, такого как isAllowedAccessForResource(), который воздействует на базовые данные для модели. Модель — это место, где необработанные данные сходятся с нашим кодом приложения.
  • Вид: представление вашей модели. Представление часто является самим пользовательским интерфейсом. В представлении не должно быть никакой логики, не связанной с представлением данных. Для интерфейсных фреймворков это обычно означает, что конкретное представление было напрямую связано с ресурсом и с ним будут связаны действия CRUD (создание, чтение, обновление, удаление). Большинство интерфейсных приложений строятся иначе.
  • Контроллер: контроллеры — это «клей», который связывает модель и представление вместе. Контроллеры обычно должны быть «только» связующим звеном, и не более того (например, в них не должно быть сложного представления или логики базы данных). Как правило, вы должны ожидать, что у контроллеров гораздо меньше возможностей для изменения данных, чем у моделей, с которыми они взаимодействуют.

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

Redux обязан своим происхождением и дизайном шаблону Flux, популяризированному в Facebook. Если вы знакомы с популярным шаблоном MVC, используемым Ruby on Rails и другими платформами приложений, Flux может стать отходом от того, к чему вы привыкли. Вместо того, чтобы разбивать части вашего приложения на модели, представления и контроллеры, Flux определяет для него несколько разных частей:

  • Магазин: Магазины содержат состояние и логику приложения; они похожи на модели в традиционном MVC, но вместо того, чтобы представлять одну запись базы данных, они управляют состоянием многих объектов. В отличие от модели, мы представляем данные, однако они имеют смысл, не ограниченные ресурсами.
  • Действия: вместо того, чтобы обновлять состояние напрямую, приложения Flux изменяют свое состояние, создавая действия, которые изменяют состояние.
  • Вид: пользовательский интерфейс, обычно React, но Flux не требует React.
  • Диспетчер: центральный координатор действий и обновлений в магазинах.

Если некоторые из этих частей кажутся вам знакомыми, способ передачи данных в Flux может быть другим, если вы раньше работали с приложениями в стиле MVC. В парадигме Flux данные передаются более однонаправленно, что отличается от двунаправленного способа, применяемого реализациями типа MVC. Обычно это означает, что в приложении нет единого места, из которого поступают данные; многие различные части системы имеют право изменять состояние, и состояние часто децентрализовано во всем приложении. Этот подход хорошо работает во многих случаях, но в больших приложениях может возникнуть путаница при отладке и работе.

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

Это может не обязательно быть проблемой для небольших приложений и даже может работать хорошо для больших приложений, но это может стать более сложным в нетривиальных клиентских приложениях. Например, что происходит, когда элементы, необходимые для модификации модели, используются в пятидесяти разных местах, а шестидесяти различным контроллерам необходимо знать об изменениях состояния? Ситуация усложняется тем, что представления иногда действуют как модели в некоторых интерфейсных фреймворках (состояние еще более децентрализовано). Где источник правды для ваших данных? Если он распределен по представлениям, множеству разных моделей и все это в умеренно сложной настройке, мысленно отслеживать все будет сложно. Это также может привести к несогласованному состоянию приложения, которое вызывает ошибки приложения, и это не проблема «только для разработчиков», напрямую затронуты и конечные пользователи.

Одна из причин, по которой это сложно, заключается в том, что люди, как правило, не умеют рассуждать об изменениях, которые происходят с течением времени. Чтобы понять это, представьте себе доску для игры в шашки. Несложно удержать в голове один или несколько снимков доски. Но сможете ли вы отслеживать каждый снимок доски после двадцати ходов? Тридцать? Всю игру? Мы должны создавать системы, о которых нам легче думать и использовать, потому что сложно отслеживать мысленно асинхронные изменения данных с течением времени. Например, подумайте о вызове удаленного API и использовании данных для обновления состояния вашего приложения. Просто для нескольких случаев, но что, если вам нужно вызвать пятьдесят разных конечных точек и отслеживать входящие ответы, пока пользователь все еще использует приложение и вносит изменения, которые могут привести к большему взаимодействию с API? Бывает сложно мысленно выстроить их все в ряд и предсказать, каким будет результат изменений.

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

Как Flux выглядит в коде? Это в первую очередь парадигма, и существует множество доступных библиотек, реализующих основные идеи Flux. Все они немного отличаются друг от друга тем, как реализуют Flux. Redux тоже делает то же самое, несмотря на то, что его особая разновидность Flux получила наибольшее распространение и признание. Другие библиотеки Flux включают Flummox, Fluxxor, Reflux, Fluxible, Lux, McFly и MartyJS (хотя на практике вы увидите, что они мало используются по сравнению с Redux).

Знакомьтесь, Redux: разновидность Flux

Пожалуй, самой широко используемой и известной библиотекой, реализующей идеи, лежащие в основе Flux, является Redux. Redux — это библиотека, реализующая идеи Flux в несколько измененном виде. В собственной документации Redux описывается как «контейнер с предсказуемым состоянием для приложений JavaScript». Конкретно это означает, что это библиотека, которая по-своему реализует на практике концепции и идеи Flux.

Точное определение того, что считается и что не считается Flux, здесь не важно, но мы должны рассмотреть некоторые различия импорта между парадигмами Flux и Redux, в том числе

  • Redux использует одно хранилище: вместо того, чтобы размещать информацию о состоянии в нескольких хранилищах приложения, приложения Redux хранят все в одном месте. Во Flux у вас может быть много разных магазинов. Redux отказывается от этого и использует единое глобальное хранилище.
  • Redux представляет редукторы: более неизменяемый подход к мутации («редукторы»): в Redux состояние изменяется предсказуемым и детерминированным образом, по одной части состояния за раз и только в одном месте (глобальное хранилище).
  • Redux представляет промежуточное программное обеспечение: поскольку действия и данные передаются однонаправленным образом, вы можете добавить промежуточное программное обеспечение в свое приложение Redux и внедрить собственное поведение по мере обновления данных.
  • Действия Redux отделены от хранилища: создатели действий ничего не отправляют в хранилище; вместо этого они возвращают объекты действий, которые использует центральный диспетчер.

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

Настройка для Redux

Redux — это парадигма архитектуры вашего приложения, но это также и библиотека, которую вы можете установить. Это одна из областей, где Redux превосходит «сырую» реализацию Flux. Существует множество реализаций парадигмы Flux — Flummox, Fluxxor, Reflux, Fluxible, Lux, McFly, MartyJS и многие другие — и все они имеют разную степень поддержки сообщества и разные API. Redux пользуется сильной поддержкой сообщества, но у библиотеки Redux есть небольшой мощный API, который помог ей стать одной из самых популярных и надежных библиотек для архитектуры приложений React. На самом деле, достаточно часто можно увидеть, как Redux используется с React, что основные команды для каждой библиотеки часто взаимодействуют друг с другом и обеспечивают совместимость и осведомленность о функциях. Некоторые люди входят в обе команды, и, как правило, между проектами существует отличная видимость и коммуникация.

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

  • Убедитесь, что мы запустили npm install с исходным кодом из статьи (здесь: https://github.com/react-in-action/letters-social), чтобы убедиться, что все нужные зависимости установлены локально.
  • установите инструменты разработчика Redux. Это позволяет нам проверять магазин Redux и действия в браузере.

Redux предсказуем по дизайну, и это упрощает создание потрясающих инструментов отладки. Такие инженеры, как Дэн Абрамов и другие, работающие над библиотеками Redux и React, помогли создать несколько мощных инструментов для работы с приложениями Redux. Поскольку состояние в Redux изменяется предсказуемым образом, возможна отладка по-новому: вы можете отслеживать отдельные изменения в состоянии вашего приложения, проверять различия между изменениями и даже перематывать и воспроизводить состояние вашего приложения с течением времени. Расширение Redux Dev Tools позволяет вам делать все это и многое другое и поставляется в виде расширения для браузера. Чтобы установить его для своего браузера, следуйте инструкциям на https://github.com/zalmoxisus/redux-devtools-extension. На рис. 3 показан краткий обзор возможностей Redux Dev Tools.

После установки расширения вы должны увидеть новый значок Dev Tools на панели инструментов вашего браузера. На момент написания статьи оно выглядит окрашенным только тогда, когда обнаруживает экземпляр приложения Redux в режиме разработки, и если вы посещаете приложение или другие сайты, на которых не настроено Redux, расширение еще не будет работать. Но как только мы настроим приложение, вы увидите цветной значок, и при нажатии на него откроются инструменты.

И вот как вы можете начать использовать Redux.

___________________________________________________________________

Если вам не хватает дополнительной информации о веб-разработке с помощью Redux и React, прочтите бесплатную первую главу React в действии и посмотрите эту Презентацию для обмена слайдами.
______________________________________________________________________________

Об авторе:

Марк Томас — опытный инженер-программист, ежедневно работающий с React, JavaScript и Node.js. Он любит чистый код, красивые системы и хороший кофе.

Первоначально опубликовано на freecontent.manning.com.