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

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

Кроме того, нет недостатка в Javascript UI Framework, и в ATS мы использовали несколько из них для отправки рабочих приложений нашим клиентам: Dojo, ExtJS, Angular и совсем недавно React.

Циклопические потоки данных

В посте, который я написал около года назад, я описал конкретную проблему, с которой мы столкнулись при использовании Angular и управления состоянием. В частности, области использовались для внедрения данных в дочерние компоненты, что приводило к странным ошибкам времени выполнения при перегруппировке компонентов вокруг приложения. Это вдохновило на создание Eldritch Flow:

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

На момент объявления мы думали, что Flux кажется разумной архитектурой для огромных приложений, таких как Facebook, но также включает в себя значительное количество шаблонов. С момента первого объявления и реализации vanilla Flux компанией Facebook было реализовано несколько реализаций архитектуры Flux, и многие из них были встречены положительными отзывами сообщества.

Презентационные Архитектуры

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

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

Традиционный MVC

Шаблон MVC существует уже несколько десятилетий и является основным элементом дизайна для программного обеспечения iOS и OSX. В традиционном шаблоне MVC есть односторонний цикл потока данных. Представление передает действия пользователя контроллеру, который обновляет модель данных в соответствии с бизнес-правилами, который затем отправляет уведомление об изменении данных, вызывая повторную визуализацию.

Контроллер-посредник MVC

Небольшой вариант этого помещает контроллер в качестве посредника между представлением и моделью, нарушая зависимость между моделью и представлением. Этот поток данных является стандартным потоком данных MVC, как описано Apple и Google.

Модель-Просмотр-Презентатор

Паттерн Model-View Presenter аналогичен паттерну Mediating-Controller MVC с добавлением привязки данных между представлением и моделью. Это своего рода компромисс по сравнению с MVC-медиатором-контроллером, поскольку привязка данных устраняет некоторые шаблоны для представления простых свойств, но затрудняет разделение проблем между докладчиком и моделью.

Модель-представление-представление-модель MVVM

Архитектура модель-представление-представление-модель, представленная Microsoft, представляет собой шаблон представления, зависящий от двусторонней привязки данных и концепции «модели представления». В этом контексте модель представления - это модель, описывающая состояние конкретного представления, и взаимодействующая с более общей моделью предметной области посредством синхронных обновлений или событий. Эта архитектура распространена в современных системах Microsoft, KnockoutJS и более поздних версиях Angular.

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

AngularJS «MVC»

AngularJS 1.x был интересным фреймворком. Это было большим улучшением по сравнению с существующими веб-фреймворками, но в нем были хорошо - известные недостатки (область действия, определение директивы, модули) и реализация MVC, которая была гибридом между MVP и MVVM. Модели в Angular неявно создавались системой в Scope, и разработчики взаимодействовали с моделями, инициализируя их в контроллерах и манипулируя ими из представлений. Модели могли быть связаны с представлениями и контроллерами, а контроллеры отвечали за обработку пользовательских событий.

Синтаксис контроллер как был введен, чтобы помочь уменьшить проблемы, связанные с областью видимости, и позволить разработчикам проектировать контроллеры как экземпляры классов. Это было большим улучшением и изменило природу MVC Angular, сделав его полноценным MVVM.

Поток

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

Этот односторонний цикл потока данных повторяет традиционный цикл потока данных MVC с некоторыми дополнительными инвариантами:

  1. Представления используют одностороннюю привязку и обрабатывают хранилища данных как неизменяемые. Они синхронны. Все действия пользователя, изменяющие состояние, представлены в виде объектов action.
  2. Действия, аналогичные контроллеру MVC, разрешают асинхронное взаимодействие с моделью предметной области и отправляют результаты в магазины. Действия должны иметь уникальное имя и полезную нагрузку.
  3. Хранилища данных, аналогичные MVC View или MVVM ViewModel, отвечают синхронно на события и управляют состоянием приложения.

Существует несколько реализаций архитектуры Flux, большинство из которых соответствуют дизайну, предписанному Facebook. Один из наиболее интересных вариантов, Redux, немного упрощает этот дизайн, устраняя роль диспетчера, объединяя хранилища в единый контейнер состояния и помещая инварианты в управление состоянием:

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

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

  1. Компоненты просмотра преобразуют состояние приложения в визуализированную модель DOM.
  2. Действия преобразуют намерения пользователя в потоки событий.
  3. Редукторы переводят события в состояние приложения.

Какую архитектуру я должен использовать?

Инженерное дело - это компромисс, а не совершенство. Вы должны понимать последствия любого выбранного вами шаблона презентации. Выбор между архитектурой Flux или MVVM представляет собой компромисс между сокращенным шаблоном и предсказуемостью.

В ATS мы в восторге от возможностей Flux и Redux. Мы считаем, что структуры, которые активно продвигают передовой опыт, превосходят те, которые этого не делают. Одна из наших самых больших претензий к Angular заключалась в том, что в их примерах кода подчеркиваются легко понятные конструкции кода, не соответствующие лучшим практикам. Flux и Redux активно продвигают макет приложения и инварианты кода, которые поощряют лучшие практики.

Концепция Redux Time Travel полна возможностей. С помощью Time Travel приложение может быть полностью повторно отображено из документа состояния приложения. Это имеет очевидные последствия для отладки в режиме разработки, но представьте, что эта концепция применяется к интеграционному тестированию, поддержке клиентов, совместной работе или сохранению рабочего пространства.

Если вы хотите глубже погрузиться в Flux и Redux, я предлагаю начать с прекрасных мультфильмов Лин Кларка по этим темам: A Cartoon Guide to Flux и A Cartoon Intro to Redux.

В моем следующем посте я расскажу о нашем опыте работы с двумя разными реализациями Flux, Alt и Redux, и раскрою некоторые реальные примеры кодирования.