Разъяснение плюсов и минусов Вяза

Я экспериментировал с Elm on & off с середины 2017 года. Короче говоря, у нас с Эльмом сложные отношения. Я люблю Elm как язык - синтаксис немного не мешает вам и позволяет сосредоточиться на том, что вы на самом деле пишете. Составитель - строгий, но любящий учитель. Кроме того, очень приятно быть уверенным, что компилируемый код не будет генерировать исключения времени выполнения.

В то же время остальная часть интерфейсной экосистемы стремительно развивается (по многим направлениям!), А я использую React на работе, поэтому сложно посвятить значительную часть своего свободного времени изучению Elm.

Для тех из вас, кто не слишком знаком с Elm, это функциональный язык компиляции в JavaScript, который в основном используется для создания надежных, устойчивых к ошибкам пользовательских интерфейсов. Хотя это совершенно другой язык, чем JavaScript, предполагаемый вариант использования делает его прямым конкурентом других сред JavaScript, таких как React, Angular и Vue. Однако различия огромны (к лучшему или к худшему) - на самом деле вяз - это совершенно другой язык!

Выбор любого языка означает выбор набора сопутствующих ему компромиссов. Вот несколько аспектов, которые мне очень нравятся в Вязе, и некоторые, которые меня не совсем устраивают.

Make-Its: почему я люблю вяз как язык

1. Надежный набор текста

Elm - это строго типизированный язык, в отличие от слабой типизации JavaScript. Это означает, что все объявленные вами функции имеют подпись типа.

Например, если бы я написал функцию с именем add, которая принимает два числа и возвращает добавленный результат, это будет выглядеть так.

JavaScript

const add = (a, b) => a + b

Вяз

add: Number -> Number -> Number 
add a b = 
    a + b

Ключ к строгой типизации имеет значение, когда я хочу вызвать функцию. Что произойдет, если я забуду передать число и вместо этого передам строки в качестве параметров?

JavaScript

const sum = add('a', 'b') // returns the string "ab" 🤔

Вяз

sum = add "a" "b" -- throws a compiler error that's helpful! 🎉

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

Хотя в JavaScript было несколько попыток перенести в него типы (в частности, Flow и TypeScript), они оба сильно отстают от синтаксиса типов и возможностей проверки статического типа Elm. В Elm объявления типов больше напоминают первоклассного гражданина, побуждая разработчиков чаще думать о типах.

2. Принудительная обработка ошибок

В Elm компилятор действительно разозлится, если вы не обработаете потенциальные точки отказа в коде своего приложения.

Например, предположим, что вы делаете сетевой запрос для некоторого JSON. Вы собираетесь использовать этот JSON-объект для рендеринга сообщения в блоге (например, того, который вы читаете. Спасибо 😜). Вы ожидаете, что JSON будет выглядеть так.

{ 
  "title": "Some cool stuff about Elm", 
  "body": "It's fun!", 
  "author": "Benjamin Johnson", 
  "dateCreated": "2018-01-25" 
}

Легко, правда? Вы просто получаете JSON и используете соответствующие ключи для рендеринга сообщения в блоге.

Не так быстро.

Что произойдет, если сеть выйдет из строя между тем, когда пользователь загрузил вашу веб-страницу, и когда они сделали этот запрос? Что произойдет, если JSON отправит обратно массив авторов вместо String? Что произойдет, если dateCreated равно null?

Все это возможности, особенно если вы полагаетесь на сторонний API для доставки контента или работаете с другими разработчиками. Как бы вы ни хотели сказать: «Этого не должно происходить. Бэкэнд-инженеры сообщат мне, когда они изменят полезную нагрузку »- дело в том, что иногда такие проблемы случаются даже в лучших организациях.

В JavaScript вы можете (не говоря, что вы всегда делаете это и определенно не говорите, что вам следует) написать код, предполагающий, что ответ JSON загружается каждый раз идеально. Вы можете не узнать, что ваше приложение не удалось, пока не получите сообщение об ошибке Cannot read property `body` of `undefined`. Теперь вам нужно пролезть через отладчик. Или вы случайно выводите на экран слово null. Не лучший UX по большому счету.

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

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

3. Чисто функциональный

Хотя чисто функциональный язык прекрасен, чистота без какой-либо формы управления состоянием не подходит для пользовательских интерфейсов (нам нужно иметь возможность реагировать на ввод пользователя и изменения состояния 😜). Elm сохраняет язык чистым, управляя мутациями состояний внутри среды выполнения Elm. Этот метод управления обновлениями состояния, более известный как Архитектура Вяза, также довольно распространен за пределами сообщества Вязов (яркий пример - React + Redux).

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

Break-Its: Почему меня не продает на 100% Elm

1. Трудно превзойти экосистему JavaScript

Что бы вы хотели сказать об «усталости от JavaScript» и о том, что каждую неделю появляется новый фреймворк: существует тонна конкуренции в мире интерфейсного JS, и в результате лучшие решения становятся верх (обычно).

Кроме того, если вы играете с новым фреймворком JS, обычно не так уж сложно интегрировать его с другими частями вашего любимого интерфейсного стека (CSS / SCSS / LESS / CSS-in-JS, служебные библиотеки и т. Д.) .

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

Я большой поклонник того, чтобы оставаться минимальным и использовать сторонние зависимости только тогда, когда они вам нужны, но прекрасная часть экосистемы JS заключается в том, что вы можете использовать эти пакеты в NPM, когда вам нужно быстро двигаться или когда вы хотите изолировать конкретная концепция, которую вы изучаете (то есть вы хотите изучить Vue только как основу, поэтому вы используете Vue Material или Bootstrap, чтобы не тратить все свое драгоценное время на стилизацию своих компонентов).

2. Создание HTML-шаблонов немного странно

Сообщество Elm утверждает, что со временем вы привыкаете к синтаксису HTML, но меня он так и не понял. Вот краткий пример «шаблона» (или функции «просмотра») Elm.

view model = 
    div [] [ 
        button [ onClick Decrement ] [ text " - " ] 
        , div [] [ text (toString model) ] 
        , button [ onClick Increment ] [ text " + " ] 
    ]

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

Сравните это с чем-то вроде JSX, который намного ближе к необработанному HTML.

const view = model => ( 
  <div> 
    <button onClick={Decrement}> - </button> 
    <div>{model}</div> 
    <button onClick={Increment}> + </button> 
  </div> 
)

Или что-то вроде синтаксиса шаблона Vue, который просто построен поверх HTML.

<div> 
  <button v-on:click="Decrement"> - </button> 
  <div>{{model}}</div> 
  <button v-on:click="Increment"> + </button> 
</div>

На мой взгляд, синтаксис шаблонов React и Vue немного легче читать и быстро, хотя они могут быть не такими гибкими и компонуемыми, как HTML-функции Elm.

3. Отсутствие поддержки со стороны крупной компании.

С одной стороны, я не решаюсь даже противопоставить это Elm как языку. Язык должен стоять или падать из-за того, что он действует изолированно (в идеальном мире…).

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

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

Заключение

Я по-прежнему считаю, что Elm стоит изучить на 100% - если у вас есть время. Это ценно тем, что заставляет задуматься о программировании. Что произойдет, если в JSON, который вы получаете от сервера, нет ключа, который вы ожидаете? Что, если браузер пользователя не может предоставить вам данные о геолокации? (Оба были источниками особенно сложных ошибок в JS, над которыми я работал в прошлом году или около того).

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

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

Нравится то, что вы читаете? Не согласны? Не стесняйтесь твитнуть мне или связаться со мной в LinkedIn. Спасибо за прочтение!

Первоначально опубликовано на www.benjaminjohnson.me.