Использование Вяза в редакции

Сильная типизация и полезный компилятор делают его полезным для быстрой разработки, но он еще недостаточно развит, чтобы заменить JavaScript.

Как члены небольшой группы разработчиков новостей в The Times и The Sunday Times, создающие большое количество программного обеспечения на высокой скорости, мы сталкиваемся с очень специфическим набором проблем. Поскольку мы работаем над всем, от внутренних инструментов до интерактивных историй и информационных бюллетеней по электронной почте, мы должны изучить широкий спектр технологий. Нам также приходится часто переключаться между ними: нет ничего необычного в том, чтобы работать над тремя разными проектами в день. И мы должны действовать быстро, работая в сроки, которые меняются так же часто, как заголовки.

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

Elm - это функциональный язык со статической типизацией для интерфейсной веб-разработки. Он приносит с собой все, что есть в этих парадигмах, таких как чистота, неизменяемость и проверка типов, а затем компилируется в JavaScript. Вы можете думать об этом как о замене React или других фреймворков, хотя это отдельный язык сам по себе.

Прочитав немного, я решил сразу погрузиться в него и использовать его в течение недели, чтобы создать относительно простой автономный проект: наш путеводитель по трансферному окну Премьер-лиги. Вот что я нашел.

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

Тогда есть преимущества статической типизации. Поскольку каждая функция и фрагмент данных должны быть явно помечены своим типом, компилятор Elm может проанализировать вашу программу и выявить проблемы до того, как они возникнут: больше не будет случайной обработки строки как числа, или «undefined не является функцией»! Это помогает избежать целого класса ошибок.

Действительно, компилятор Elm - это то место, где язык действительно сияет. Много работы было вложено в полезные сообщения об ошибках, поэтому работать с ними - настоящее удовольствие. Написали оператор case (переключение) и забыли учесть возможное значение? Без проблем:

Все еще придумываете язык или просто склонны к опечаткам? Компилятор Elm дает вам полезные советы:

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

type alias TeamData =
  { author: String
  , copy : List CopyData
  , name : String
  , transfers : List TransferData
  }

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

Например, вот простая функция, которая принимает команду и возвращает некоторый HTML-код, отображающий название команды и автора. Первая строка - это аннотация типа, которая показывает, что функция ожидает параметр типа TeamData и вернет HTML; остальное - тело функции:

displayTeamName : TeamData -> Html a
displayTeamName team =
  div [ class "team" ]
    [ div [ class "name" ] [ text team.name ]
    , div [ class "author" ] [ text team.author ]
  ]

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

Однако у разработки Elm есть свои недостатки. Это не ошибка языка, а тот факт, что он настолько новый (v0.17 вышла только в мае 2016 года), означает, что может быть трудно найти руководства или примеры кода, которые одновременно полезны и актуальны. На официальном веб-сайте есть полезное введение в основы, но не содержится подробного описания более сложных тем, в то время как документация по библиотекам core и HTML отлично подходит для справки, но не может заменить хорошее руководство.

Между тем зарождающееся сообщество означает, что готовых к производству пакетов сторонних производителей не хватает. В знак признания этого у Elm есть порты, которые позволяют библиотекам JavaScript и коду Elm взаимодействовать. Вот пример порта на стороне Elm, который прослушивает список значений JSON:

port transfersJson : (List Json.Value -> msg) -> Sub msg

А со стороны JavaScript:

const transfers = [
  {
    team: 'Arsenal',
    player: 'John Smith'
  }
];
transferWindowApp.ports.transfersJson.send(transfers);

По нашему опыту, этот подход хорошо работал для библиотеки, такой как Tabletop, которая могла просто захватить некоторые данные и отправить их в Elm, как указано выше, но мы изо всех сил пытались интегрировать более сложные библиотеки, такие как HammerJS, что требует знания модели DOM, которую Elm рендеринг.

Говоря о JSON, подход Элма к декодированию строк JSON в пригодные для использования данные… сложен. Самым большим виновником здесь было отсутствие понятных руководств, но мне потребовалось немало времени, чтобы выяснить взаимосвязь между данными, декодерами, а затем функциями, которые на самом деле запускают декодеры. Хотя в Elm имеет смысл явно указывать тип каждого свойства JSON и учитывать потенциальные сбои при декодировании, это действительно казалось проблемой по сравнению с простым JSON.parse в JavaScript - особенно для наших данные, которые поступили из внутреннего источника с почти гарантированной точностью.

Наконец, в экосистеме Elm отсутствует поддержка использования языка в производственной среде - вероятно, потому, что очень немногие организации приняли его. Одна из проблем, с которой я столкнулся, заключалась в том, что elm -actor, основная система live-reload для разработки, не очень хорошо работает с портами, поэтому нам пришлось на раннем этапе вручную запускать компилятор каждый раз, когда мы изменил наш код. (Эван Чаплики, создатель Elm, сказал, что в будущих выпусках больше внимания будет уделяться производству.)

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

Мог бы я снова использовать его в производстве? Может быть. Это убедительное предложение, и для небольших проектов, таких как интерактивное окно передачи, оно кажется таким же хорошим вариантом, как React (который, как утверждается, превосходит его) или что-то еще, что мы используем в настоящее время. Для крупномасштабных продуктов мы, вероятно, пока будем придерживаться JavaScript, но спросите меня еще раз через год, когда у языка и сообщества будет шанс повзрослеть, и ответ может быть совсем другим.

А пока мы вносим свой вклад, открывая исходный код кода Elm для нашего проекта окна передачи: вы можете найти его на Github здесь.