Функциональное программирование берет верх над пользовательскими интерфейсами с помощью Pure Views.

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

Дэвид Нолен дает одно из лучших объяснений этого типа шаблона разработки пользовательского интерфейса ƒ (d) = V. Это функция, которая получает данные на входе и возвращает представление. Нет области видимости, привязки, создания подклассов, внешнего доступа к переменным или каких-либо побочных эффектов. Это делает его очень предсказуемым с резко меньшим учетом контекста, в котором выполняется Pure View. В мире JavaScript можно сказать, что любой JSON ВСЕГДА создает одинаковые HTML, CSS и прослушиватели событий.

Почему чистые представления отличаются от других шаблонов пользовательского интерфейса?

Чтобы полностью понять это, нам нужно понять, что мы неявно делали в течение многих лет в нашем коде. Код написан как серия сложных перестановок. Каждая вызываемая нами функция меняет что-то за пределами своей частной области видимости. Затем мы вызываем другую функцию, которая меняет что-то еще. Если данные или порядок вызовов этих функций каким-либо образом изменяются, ошибки возникают неожиданным образом. Подумайте о тех случаях, когда вы исправляли ошибку, которая была вызвана чем-то, казалось бы, не связанным с другим классом или где-то на сервере. Это большие проблемы с перестановкой.

Взгляните на таблицу ниже. Это то, как мы внутренне думаем о наших приложениях.

Супер ясно, правда? Вызовите `login ()`, затем `getUser ()`, затем `getCart ()`. На самом деле наш поток приложений включает в себя пути ошибок, неожиданные значения, сетевые и поточные операции. Если они возвращаются в несколько ином порядке, или данные немного отличаются, или данные изменяются несколькими классами в наших приложениях, это вызовет ошибки. Это более точная модель возможных ветвей:

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

Просто стало легко

Для тех, кто знаком с Бандой четырех и объектно-ориентированными шаблонами, но не видел выступления Рича Хикки Простое и понятное, посмотри сейчас. Основная концепция, о которой говорит Хики, заключается в том, что слишком много внешних факторов является основной причиной, по которой мы не полностью понимаем, что делает наш код, когда мы его читаем. Это непросто, потому что одновременно вращается слишком много тарелок. В объектно-ориентированных языках есть шаблоны, которые пытаются уменьшить эту сложность за счет использования инкапсуляции. Функциональные языки, наоборот, в значительной степени ориентированы на возможность компоновки как ключевую особенность в снижении сложности. Лучшее сочетание того и другого необходимо, чтобы лучше контролировать наши пользовательские интерфейсы.

Pure Views привносит некоторые преимущества функциональных языков в объектно-ориентированный мир, в котором живет большинство разработчиков. В функциональных языках чистая функция выполняет только одно действие и не имеет побочных эффектов (побочный эффект означает, что она ни на что не влияет, только вернуть новое значение). Несколько простых функций могут быть составлены разными способами для получения различных типов выходных данных. Перефразируя Рича Хики; Просто значит делать что-то одно. Легко означает то, что мы можем понять. В случае Pure Views, глядя на функцию рендеринга, мы должны понимать все возможные результаты. Это снижает потребность в понимании всей кодовой базы, чтобы знать, как она может повлиять на одну функцию.

Вот как будет работать функциональный процесс Pure Views:

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

createView({
  getDefaultProps(){
    return {
      selectedIds: [1, 10],
      banks: [/* bank data here */]
    };
  } 
  render(){ 
    let selectedBanks = this.props.banks.filter(function(bank){
      return this.props.selectedIds.indexOf(bank.id) > -1;
    });
    let bankItems = [];
    for (let i=0; i < selectedBanks.length; i++){
      bankItems.push(
        el("BankItem", {key:i, bank:selectedBanks[i]})
      );
    }
    return el("div", null,
             el("h1", null, "Selected Banks"),
             bankItems,
             el("a", {href:"/install", "Next")
           );
  }
})

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

Расширение возможностей без добавления сложности

Поскольку Pure Views выполняет только одно действие и не влияет ни на что, выходящее за рамки их собственных возможностей, это делает его чрезвычайно гибким, не привнося дополнительных сложностей. Есть несколько случаев, которые действительно демонстрируют силу Pure Views.

Первый называется Горячая замена модуля. Если вы думаете, что это похоже на Live Reloading в браузере, вы ошиблись. В тот момент, когда вы сохраняете файл в своем редакторе, только обновленный код может быть отправлен в ваше приложение, заменяет старый код, запускается функция рендеринга для этого представления, и изменяется только HTML-код, который отличается. Это не повлияет на весь уровень данных приложения. Это работает с макетами, иерархиями представлений и обработчиками событий. Данные в приложении не меняются, поэтому вид обновляется в режиме реального времени. Существуют библиотеки для поддержки этого в браузерах, приложениях iOS, Android, Windows и Mac. Когда время итерации между внесением изменения в код и просмотром вывода близко к 0, это полностью меняет ваш рабочий процесс кодирования.

Следующее - Отладка путешествия во времени. Это действительно потрясающе, как это звучит. Без Pure Views хранение каждого распространения событий и их влияний на представление является непосильной нагрузкой для большинства систем. С Pure Views все, что нужно, - это иметь массив и отправлять новую копию данных при каждом изменении. Если вы понимаете, как работают постоянные структуры данных, вам будет еще проще сохранять каждое изменение в вашем приложении. При отладке просто перемещайтесь вперед и назад, как на видеомагнитофоне. (Да, технология пользовательского интерфейса 80-х годов и большинство UI-фреймворков сегодня не имеют ее в своем наборе инструментов для отладки). Состояние приложения можно даже сериализовать и сохранить на сервере в процессе производства, чтобы получить полные шаги репозитория практически для каждой ошибки в вашем приложении.

Последняя важная возможность - это отказоустойчивость над жесткостью. Данные не привязаны к пользовательскому интерфейсу. Это четкое разделение проблем. Уровень данных вашего приложения может фокусироваться на функциях, преобразовании данных и кэшировании, не думая обо всех проблемах, которые могут возникнуть у пользователя. В подавляющем большинстве проектов бизнес-логика практически не меняется; код для тележки для покупок в значительной степени имеет те же требования. Но на уровне просмотра дизайнеры всегда находят новые способы объяснить или прояснить интерфейс или увеличить продажи. Модульные и интеграционные тесты могут быть сосредоточены на тестировании потока приложений на чистых, простых данных. Поскольку представление - это всего лишь простое преобразование и отражение данных в любом заданном состоянии, оно гораздо менее подвержено сложностям или ошибкам. Это также означает, что когда дизайнер или бизнес-директор запрашивает изменения в представлении, это можно сделать, не влияя на функциональность потока данных.

Вернуться в реальный мир

Движение Pure Views растет. У традиционных слоев просмотра мало преимуществ перед Pure Views. Framework, которые более открыты, как Backbone, вы можете заменить системы шаблонов строк на Pure Views. Все больше и больше авторов фреймворков видят преимущества и переходят на Pure Views. Несколько известных фреймворков, которые действительно отстаивают этот подход, - это Elm, Ember 2, Om Next, ReactJS.

Чтобы воспользоваться преимуществами некоторых расширенных возможностей, предлагаемых Pure Views, есть несколько готовых инструментов, упрощающих интеграцию. Для горячей замены модуля у Webpack и React отличные настройки. У меня есть стартовый комплект под названием Megatome, который должен помочь вам начать работу над новым проектом за 2 минуты. Для отладки Time Travel посмотрите на Redux - это уровень данных, созданный для работы с React.

Последнее замечание для всех, кто зацикливается на синтаксисе (например, Lisps или JSX): не судите о книге по обложке. Если не смотреть глубже, можно полностью игнорировать возможности и силу, которые могут исходить от чего-то другого. Посмотрите еще раз на приведенный выше код, чтобы увидеть реальный Pure View выше. Это действительный код без необходимости транспиляции, менеджеров пакетов или каких-либо дополнительных шагов сборки. Не хватает только трех верхних строк:

let el = React.createElement;
let createView = React.createClass;

Мой последний проект сложнее кодирования. Мы делаем личные финансы не отстой. Посмотрите, как темп ваших расходов приводит к управлению вашим бюджетом на getfiskal.com.