С момента публикации статьи Основы разработки на языке Elm (руководство по инструментарию для начинающих) прошло полтора года. За это время в инструментарии для языка разработки веб-интерфейсов Elm произошли многочисленные изменения: появилась более удобная система сборки с возможностью генерации нового проекта; для редактора Atom набор дополнений в некоторых отношениях теперь лучше, чем для популярного тогда среди разработчиков на Elm редактора LightTable; заработал инспектор состояния приложения. Давайте пройдёмся по этому набору на простом примере.


Инструменты разработчика на языке Elm: обложка


Базовые средства Elm


Elm можно установить как пакет NPM:


npm install -g elm

Есть и другие способы установить Elm. Они описываются в официальном руководстве.


Проверим версию только что установленного Elm:


elm --version

0.18.0

elm является обёрткой для вызова отдельных утилит:


  • elm-make: сборка кода на Elm;
  • elm-package: управление пакетами на Elm;
  • elm-reactor: утилита слежения за кодом на Elm для перекомпиляции и перезагрузки его в браузере;
  • elm-repl: REPL для Elm.

Управление кодом на Elm с помощью Brunch


Одним из удобнейших средств управления кодом на Elm представляется Brunch. Устанавливается Brunch как пакет NPM:


npm install -g brunch

Проверим версию только что установленного Brunch:


brunch --version

2.10.12

Вызовем Brunch для генерации кода нашего примера проекта на Elm:


brunch new --skeleton MattCheely/elm-brunch-skeleton demo-application

После генерации кода Brunch также сразу загрузит все необходимые NPM- и Elm-пакеты.


Рассмотрим сгенерированное дерево каталогов:


  • app\: исходные тексты приложения
    • assets\:
    • index.html: минимальный документ HTML5, который будет контейнером для нашего приложения
    • css\:
    • style.css: стили для примера приложения
    • elm\: исходные тексты на Elm
    • Main.elm: главный модуль приложения на Elm
    • js\: код на JavaScript
    • app.js: пример кода, работающего отдельно от кода на Elm
  • elm-stuff\: загруженные пакеты на Elm
  • node_modules\: загруженные NPM-пакеты
  • .gitignore
  • README.md
  • brunch-config.js: настройки для Brunch с учётом поддержки Elm
  • elm-packages.json: настройки для Elm, в том числе список используемых пакетов
  • package-lock.json: список зависимостей NPM (сгенерирован NPM автоматически)
  • package.json: настройки для NPM

Уже сейчас мы можем собрать наш проект:


cd demo-application
npm build

После сборки проекта появится также папка public, в которой разместятся все части нашего веб-приложения.


Давайте запустим приложение в режиме отладки:


npm start

Откроем в браузере ссылку http://localhost:3333/ и полюбуемся на прекрасное веб-приложение:


Пример приложения на Elm


В правом нижнем углу находится интерфейс инспектора состояния приложения. Щёлкнем на нём. Сейчас счётчик value имеет значение 0:


Начальное состояние приложения


Пощёлкаем на кнопках +1 и -1 и понаблюдаем как меняется состояние:


Наблюдение за изменением состояния приложения


Мы можем вернуться к любому предыдущему состоянию:


Просмотр предыдущего состояния приложения


И даже вернуться к последнему, просто нажав на кнопку Resume.


Неискушённому зрителю читателю наверное будет интересно также узнать, как устроено приложение на Elm, но сначала давайте настроим редактор, чтобы изучать исходный код приложения было приятней и удобней.


Настройка Atom для работы с Elm


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


Перво наперво установим дополнение language-elm:


apm install language-elm

Это дополнение предоставит базовую поддержку Elm, такую как синтаксическая подсветка кода.


Для поддержки переходов к определениям и всплывающим подсказкам с типами выражений установим пакет atom-ide-ui.


apm install atom-ide-ui

Для поддержки автодополнения поставим autocomplete-plus:


apm install autocomplete-plus

Если используете сокращённый набор кода, поставьте snippets:


apm install snippets

Наконец мы готовы установить Elmjutsu:


apm install elmjutsu

Теперь мы можем открыть наш проект в Atom:


Код Elm в Atom


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


Дополнительный, но важный инструментарий


Пожалуй самый важный инструмент из дополнительных это elm-format. С помощью этой утилиты можно приводить внешний вид программы к стандартному (общепринятому) виду. Установим его:


npm install -g elm-format

Также установим соответствующее дополнение для Atom elm-format:


apm install elm-format

Благодаря этому дополнению, каждый раз, как мы будем сохранять наш код, elm-format будет его форматировать. Если в коде будет синтаксическая ошибка, то утилита её обнаружит, и мы об этом узнаем, хотя, для выяснения наличия ошибок всё же лучше использовать компилятор. А в этом нам будет помогать дополнение для Atom linter-elm-make.


Поставим его:


apm install linter
apm install linter-elm-make

Не забудьте также зайти в настройки этих дополнений и задать все необходимые параметры.


Дополнение elm-lens показывает прямо в коде для функций и типов экспонируются ли они или являются локальными, а также сколько раз на них ссылаются. Для установки дополнения просто вызовите:


apm install elm-lens

Для поддержки REPL в Atom можно установить дополнение elm-instant:


apm install elm-instant

Если вы хотите работать с терминалом прямо в Atom, рекомендую установить дополнение platformio-ide-terminal:


apm install platformio-ide-terminal

Поэкспериментируем


Для начала откроем окно терминала в Atom, нажав кнопку + в нижней части окна, и запустим слежение за нашим кодом на Elm:


npm start

Код на Elm в Atom с запущенным слежением в терминале


Давайте внесём ошибку в код:


Код на Elm в Atom с ошибкой


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


Для непосвящённых


Как и обещал, немного расскажу, как устроен код приложения на Elm. Давайте взглянем на тот исходный код, который нам сгенерировал Brunch:


module Main exposing (main)

import Html exposing (Html, text, div, button)
import Html.Attributes exposing (class)
import Html.Events exposing (onClick)

main : Program Never Model Msg
main =
    Html.beginnerProgram
        { model = initalModel
        , update = update
        , view = view
        }

-- Model

type alias Model =
    { value : Int
    }

initalModel : Model
initalModel =
    { value = 0
    }

-- Update

type Msg
    = Increment
    | Decrement

update : Msg -> Model -> Model
update msg model =
    case msg of
        Increment ->
            { model | value = model.value + 1 }

        Decrement ->
            { model | value = model.value - 1 }

-- View

view : Model -> Html Msg
view model =
    div []
        [ div [ class "counter" ]
            [ text (toString model.value) ]
        , div [ class "controls" ]
            [ button [ onClick Increment ] [ text "+1" ]
            , button [ onClick Decrement ] [ text "-1" ]
            ]
        ]

Приложение на Elm оформляется как модуль Main, экспонирующий функцию main. Это мы видим в первой строке кода. Далее идёт импорт модулей. Некоторые модули импортируются по умолчанию, но модули Html, Html.Attributes и Html.Events нужно импортировать. Здесь они импортируются с экспонированием отдельных функций и типов. Это делается, чтобы не квалифицировать имя модуля, например, вместо Html.Attributes.class будем писать просто class.


Ниже объявляется и определяется функция main. В объявлении задаётся её тип. Тип функции указывается после символа :, определение происходит после знака =. Как увидим ниже, указание имён параметров и их типов осуществляется раздельно. Elm поддерживает вывод типов, однако для функций верхнего уровня хорошим тоном считается ручное указание типа.


В нашем случае функция main вызывает функцию Html.beginnerProgram, которая получает на вход структуру с тремя полями: model, update, view. Эта функция запустит цикл обработки сообщений. Параметр model получает начальное состояние приложения, которое задано в функции initialModel. Функция update вызывается всякий раз, когда происходит какое-то событие и передаётся соответствующее сообщение. После обработки сообщения вызывается функция view, занимающаяся формированием нового дерева DOM.


Далее определяется тип Model, точнее синоним типа структуры, состоящей из поля value типа Int. Тип Int, как нетрудно догадаться, представляет целые числа.


Как уже было сказано, функция initialModel возвращает начальное значение состояния, которое содержит одно поле value со значением 0. Типом состояния может быть любой тип, не только структура.


Далее определяется тип сообщения Msg. Это тип-перечисление с двумя возможными значениями: Increment и Decrement.


Функция update получает на вход сообщение и состояние приложения. Обычно код этой функции включает в себя оператор сопоставления с образцом case .. of ... Здесь происходит изменение состояния в зависимости от пришедшего сообщения: значение поля value либо увеличивается на 1, либо уменьшается на 1.


Наконец, функция view принимает состояние приложения и формирует с помощью функций модулей Html, Html.Attributes и Html.Events требуемое дерево DOM.


Установка дополнительных пакетов Elm


И последнее, но не менее важное: чтобы установить дополнительные пакеты Elm, нужно вызвать команду elm-package. Например, установим пакет elm-community/list-extra:


elm package install elm-community/list-extra

Обратите внимание, что идентификатор пакета состоит из двух частей, то есть не просто list-extra, а elm-community/list-extra.


С этой командой связан файл проекта elm-package.json. В него записываются названия и версии устанавливаемых пакетов в разделе dependencies. Например, сгенерированный Brunch файл elm-package.json выглядит так:


{
  "version": "1.0.0",
  "summary": "helpful summary of your project, less than 80 characters",
  "repository": "https://github.com/user/project.git",
  "license": "BSD3",
  "source-directories": ["app/elm"],
  "exposed-modules": [],
  "dependencies": {
    "elm-lang/core": "5.0.0 <= v < 6.0.0",
    "elm-lang/dom": "1.1.1 <= v < 2.0.0",
    "elm-lang/html": "2.0.0 <= v < 3.0.0"
  },
  "elm-version": "0.18.0 <= v < 0.19.0"
}

Репозиторий пакетов можно просматривать здесь.


Что дальше


Пожалуй лучший источник информации об Elm это его родной сайт:



Вероятно стоит также перечитать статью Основы разработки на языке Elm (руководство по инструментарию для начинающих).


Опрос


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


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


  • 28.2%: первый раз слышу, но выглядит годным
  • 21.1%: не нужен
  • 20.5%: годный, я на нём уже программирую
  • 15.8%: сыроват для продакшн
  • 14.1%: годный, но писать на нём не собираюсь

Проголосовало 170, воздержалось 147. Прочитало статью 13,9k, добавило в закладки 51.


Интересно, наверное, будет сравнить с результатами голосования, зафиксированными автором через неделю после публикации той статьи:


  • 31%: не нужен
  • 18%: первый раз слышу, но выглядит годным
  • 18%: сыроват для продакшн
  • 18%: годный, но писать на нём не собираюсь
  • 15%: годный, я на нём уже программирую

Проголосовало 99, воздержалось 76. Прочитало статью 5,5k, добавило в закладки 41.


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


Сообщество


С момента публикации прошлой версии статьи (30 мая 2016) существует рускоязычное сообщество во Вконтакте. Число участников сообщества на момент написания этой статьи 179. Присоединяйтесь!


Ссылки





© Симоненко Евгений, 2018

Комментарии (11)


  1. easimonenko Автор
    29.01.2018 15:09

    Уважаемые читатели, если вы знаете полезные инструменты разработчика на Elm, не упомянутые в этой статье, поделитесь информацией. Интересно также узнать от разработчиков на Elm, почему вы используете другие среды разработки, отличные от Atom и LightTable? Ну и, если обнаружите какие-либо грамматические и смысловые ошибки в статье, пишите, постараюсь исправить.


  1. j_wayne
    29.01.2018 15:27

    Я — бэкендер, который был вынужден также тащить и фронтенд. Фуллстек разработчиком себя не считаю в виду слабого знания фронтенда (и невеликой любви к нему, если честно).
    Когда мне стало недоставать реактивности, я решил вместо своего привычного coffescript/jquery лапшекода, одну фичу переписать на чем-то ином. Сначала я пытался ее написать на react/redux, потом на elm и успешно написал лишь на vue.js.
    Elm концептуально очень красив! React/redux в одной платформе, да еще и с проверками при компиляции… Но требует слишком больших усилий в моем случае. На react/redux я пожалуй фичу бы дописал, но не видел смысла, получалось очень страшно и громоздко.
    Я не хочу сказать, что эти инструменты плохие. Это скорее я. Но они явно не для случая «accidental frontend developer».
    Особенные трудности были с «нечистыми» штуками, такими, как drag and drop и уже имеющимися в проекте JS библиотеками (календари, пикеры, и пр.). Вообще, в Elm той версии был какой-то интероп с ними, но работать со всем этим мне было грустно. Также это был переходной момент (то ли от 16 к 17 версии, то ли от 17 к 18, при переходе много чего убрали/сломали, но не добавили/починили).
    Еще, смущал как jsx, так и html в виде кода в Elm (у меня был отдельный верстальщик).
    Не флейма ради, реально интересует этот вопрос… Получается, что для идиллии, нужно использовать только Elm-библиотеки либо писать виджеты самому?


    1. easimonenko Автор
      29.01.2018 15:48

      Спасибо за комментарий! Всё так. Да, с готовым кодом на JavaScript он плохо сочетается. Поэтому вся надежда на развитие базы родных для Elm пакетов. На мой взгляд Elm хорошо подходит для разработки SPA, с учётом, что текущих возможностей будет достаточно, либо готовы писать какие-то вещи с нуля или писать нативные модули для использования кода на JavaScript.


    1. potan
      29.01.2018 17:43

      Я тоже бэкендер, но начал писать странички для отладки и внутреннего использования на Elm. Единственное неудобство, с которым я сталкнулся — приходится разбираться в css (все больше склоняюсь к тому, что бэкендер этого понять не может).
      С js раньше сталкивался практически только как со встроенным языком в cwl, когда проходил курс на stepic. Этого мне вполне хватило, что бы я решил с ним по возможности не связываться.


      1. j_wayne
        30.01.2018 13:50

        Вот то-то и оно, слишком много специфических прикладных знаний надо. Разные версии браузеров и т.п. Есть причины делегировать верстку верстальщику. Но чтобы он еще jsx или Elm.Html умел… утопия(


    1. kklaustrum
      30.01.2018 13:40
      +2

      Получается, что для идиллии, нужно использовать только Elm-библиотеки либо писать виджеты самому?

      Есть проект порта material design на elm с неплохими демо --> debois.github.io/elm-mdl — это к вопросу о «писать виджеты самому». Другое дело, что стоит сделать шаг в сторону для ещё доков, как примеры работы с elm-mdl остаются до сих пор для v0.17, а не v0.18.

      Еще, смущал как jsx, так и html в виде кода в Elm (у меня был отдельный верстальщик)

      Можно не верстать прямо elm-кодом (хотя свои плюсы у такого подхода найдутся со временем), а попробовать этот сервис по переводу из «обычной» верстки --> mbylstra.github.io/html-to-elm/

      Но со временем, в той или иной степени, наверно правильнее отдавать всё бОльшую и бОльшую часть верстки в elm-экосистему. Ставя с elm packages штуки вроде rtfeldman/elm-css/latest и пр. Просто иначе elm не раскроется, как мне кажется. Раз уж пал выбор на новую экосистему, то вытягивать из неё по максимуму, а не чуть-чуть.


      1. easimonenko Автор
        30.01.2018 13:46
        +1

        Есть проект порта material design на elm с неплохими демо --> debois.github.io/elm-mdl — это к вопросу о «писать виджеты самому».

        Использую в одном своём проекте. Хорош, если нужен сложный интерфейс, и хочешь, чтобы как в Android. В тоже время есть поддержка Bootstrap: http://elm-bootstrap.info/ https://github.com/rundis/elm-bootstrap


      1. potan
        30.01.2018 17:55

        У меня с elm-mdl возикли проблемы с tooltip при появлении горизонтального скролинга.
        Не уверен, что смогу с ними справиться, если освою css, но есть желание попробовать.


    1. easimonenko Автор
      30.01.2018 15:49

      Еще, смущал как jsx, так и html в виде кода в Elm (у меня был отдельный верстальщик).

      Кстати, для вставки готового HTML можно использовать пакет http://package.elm-lang.org/packages/evancz/elm-markdown/latest


      1. j_wayne
        30.01.2018 15:50

        А это работает с реактивностью?


        1. easimonenko Автор
          30.01.2018 15:54

          Вроде нет. Может быть и есть способ покопаться в DOM, но мне не надо было.