Spec-Zone.ru › Elixir 1.17

Источник Введение в Mix

В этом руководстве мы создадим полное приложение Elixir с собственной системой управления, конфигурацией, тестами и многим другим.

Требования к этому руководству (см. elixir -v):

  • Elixir 1.15.0 и выше
  • Erlang/OTP 24 и выше

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

CREATE shopping
OK

PUT shopping milk 1
OK

PUT shopping eggs 3
OK

GET shopping milk
1
OK

DELETE shopping eggs
OK

Для создания нашего приложения ключ-значение мы будем использовать три основных инструмента:

  • OTP (Open Telecom Platform) — набор библиотек, поставляемый с Erlang. Разработчики Erlang используют OTP для создания надёжных, отказоустойчивых приложений. В этой главе мы рассмотрим, как многие аспекты OTP интегрируются с Elixir, включая деревья управления, обработчики событий и многое другое;

  • Mix — инструмент сборки, поставляемый с Elixir, который предоставляет задачи для создания, компиляции, тестирования вашего приложения, управления его зависимостями и многим другим;

  • ExUnit — основанный на ExUnit фреймворк для тестирования, поставляемый с Elixir.

В этой главе мы создадим наш первый проект, используя Mix, и рассмотрим различные возможности OTP, Mix и ExUnit по ходу работы.

Исходный код

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

Это руководство обязательно для прочтения?

Это руководство не обязательно для прочтения в вашем путешествии с Elixir. Мы объясним.

Как разработчик Elixir, вы, скорее всего, будете использовать один из многих существующих фреймворков при написании кода Elixir. Phoenix обрабатывает веб-приложения, Ecto взаимодействует с базами данных, вы можете создавать встроенное программное обеспечение с Nerves, Nx предоставляет возможности машинного обучения и проектов ИИ, Membrane собирает аудио/видео обработку, Broadway обрабатывает ввод и обработку данных, и многие другие. Эти фреймворки обрабатывают низкоуровневые детали конкурентности, распределённости и отказоустойчивости, поэтому вы, как пользователь, можете сосредоточиться на своих собственных потребностях и задачах.

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

Наш первый проект

При установке Elixir, помимо получения elixir, elixirc и iex исполняемых файлов, вы также получаете исполняемый скрипт Elixir, названный mix.

Давайте создадим наш первый проект, вызвав mix new из командной строки. Мы передадим путь к проекту в качестве аргумента (kv в данном случае). По умолчанию имя приложения и имя модуля будут извлечены из пути. Поэтому мы скажем Mix, что наш основной модуль должен быть всёзаглавным KV, а не по умолчанию, который был бы Kv:

$ mix new kv --module KV

Mix создаст директорию, названную kv, с несколькими файлами в ней:

* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/kv.ex
* creating test
* creating test/test_helper.exs
* creating test/kv_test.exs

Давайте кратко рассмотрим эти сгенерированные файлы.

Исполняемые файлы в PATH

Mix — это исполняемый файл Elixir. Это означает, что для запуска mix вам необходимо иметь как mix, так и elixir исполняемые файлы в вашей переменной среды PATH. Именно это происходит при установке Elixir.

Компиляция проекта

Файл с именем mix.exs был сгенерирован внутри папки нового проекта (kv), и его основная задача — настройка нашего проекта. Давайте посмотрим на него:

defmodule KV.MixProject do
  use Mix.Project

  def project do
    [
      app: :kv,
      version: "0.1.0",
      elixir: "~> 1.11",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  # Run "mix help deps" to learn about dependencies
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"},
    ]
  end
end

Наш mix.exs определяет две публичные функции: project, которая возвращает конфигурацию проекта, такую как имя проекта и версию, и application, которая используется для генерации файла приложения.

Также есть приватная функция с именем deps, которая вызывается из функции project, которая определяет наши зависимости проекта. Определение deps как отдельной функции необязательно, но это помогает поддерживать чистоту конфигурации проекта.

Mix также генерирует файл по адресу lib/kv.ex с модулем, содержащим ровно одну функцию, называемую hello:

defmodule KV do
  @moduledoc """
  Documentation for KV.
  """

  @doc """
  Hello world.

  ## Examples

      iex> KV.hello()
      :world

  """
  def hello do
    :world
  end
end

Эта структура достаточно для компиляции нашего проекта:

$ cd kv
$ mix compile

Выведет:

Compiling 1 file (.ex)
Generated kv app

Файл lib/kv.ex был скомпилирован, и был сгенерирован манифест приложения под названием kv.app. Все артефакты компиляции помещаются в директорию _build с помощью опций, определённых в файле mix.exs.

После компиляции проекта вы можете запустить сеанс iex внутри проекта, выполнив команду ниже. -S mix необходима для загрузки проекта в интерактивную оболочку:

$ iex -S mix

Мы будем работать над этим kv проектом, внося изменения и пробуя последние изменения из сеанса iex. Хотя вы можете начать новый сеанс всякий раз, когда происходят изменения в исходном коде проекта, вы также можете перекомпилировать проект изнутри iex с помощью вспомогательной функции recompile, как показано ниже:

iex> recompile()
Compiling 1 file (.ex)
:ok
iex> recompile()
:noop

Если что-то нужно было скомпилировать, вы увидите информативное сообщение и получите атом :ok, в противном случае функция молчит и возвращает :noop.

Запуск тестов

Mix также сгенерировал соответствующую структуру для запуска тестов нашего проекта. Проекты Mix обычно следуют соглашению о наличии файла <filename>_test.exs в директории test для каждого файла в директории lib. По этой причине мы уже можем найти test/kv_test.exs, соответствующий нашему файлу lib/kv.ex. Пока он не делает многого:

defmodule KVTest do
  use ExUnit.Case
  doctest KV

  test "greets the world" do
    assert KV.hello() == :world
  end
end

Важно отметить несколько моментов:

  1. файл теста — это файл Elixir-скрипта (.exs). Это удобно, так как нам не нужно компилировать файлы тестов перед их запуском;

  2. мы определяем модуль теста под названием KVTest, в котором мы use ExUnit.Case для ввода API тестирования;

  3. мы используем один из импортированных макросов, ExUnit.DocTest.doctest/1, чтобы указать, что модуль KV содержит доктесты (мы обсудим их в последующей главе);

  4. мы используем макрос ExUnit.Case.test/2 для определения простого теста;

Mix также сгенерировал файл под названием test/test_helper.exs, который отвечает за настройку фреймворка тестов:

ExUnit.start()

Этот файл будет необходим Mix каждый раз перед запуском тестов. Мы можем запустить тесты с помощью:

$ mix test
Compiled lib/kv.ex
Generated kv app
Running ExUnit with seed: 540224, max_cases: 16
..

Finished in 0.04 seconds
1 doctest, 1 test, 0 failures

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

Кроме того, вы можете видеть, что ExUnit печатает точку для каждого успешного теста и автоматически рандомизирует тесты. Давайте сделаем тест неудачным намеренно и посмотрим, что произойдёт.

Измените утверждение в test/kv_test.exs на следующее:

assert KV.hello() == :oops

Теперь снова запустите mix test (обратите внимание, что на этот раз компиляция не будет):

  1) test greets the world (KVTest)
     test/kv_test.exs:5
     Assertion with == failed
     code:  assert KV.hello() == :oops
     left:  :world
     right: :oops
     stacktrace:
       test/kv_test.exs:6: (test)

.

Finished in 0.05 seconds
1 doctest, 1 test, 1 failure

Для каждой ошибки ExUnit выводит подробный отчёт, содержащий имя теста с тестом, код, который завершился ошибкой, и значения левой и правой части (RHS) оператора ==.

На второй строке ошибки, сразу под именем теста, указано место, где тест был определён. Если вы скопируете местоположение теста полностью, включая имя файла и номер строки, и добавите его к mix test, Mix загрузит и запустит только этот конкретный тест:

$ mix test test/kv_test.exs:5

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

Наконец, стек отладки относится к самой ошибке, предоставляя информацию о тесте и часто о месте возникновения ошибки в исходных файлах.

Автоматическое форматирование кода

Один из файлов, сгенерированных командой mix new, — это файл .formatter.exs. Elixir поставляется с форматировщиком кода, способным автоматически форматировать наш код в соответствии с согласованным стилем. Форматировщик запускается с помощью задачи mix format. Сгенерированный файл .formatter.exs настраивает, какие файлы должны быть отформатированы при запуске mix format.

Чтобы попробовать форматировщик, измените файл в директориях lib или test, чтобы добавить дополнительные пробелы или дополнительные новые строки, например, def hello do, а затем запустите mix format.

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

Для компаний и команд мы рекомендуем разработчикам запускать mix format --check-formatted на своих серверах непрерывной интеграции, гарантируя, что весь текущий и будущий код соответствует стандарту.

Дополнительные сведения о форматировщике кода можно получить, ознакомившись с документацией по задаче форматирования или прочитав заявление о выпуске Elixir v1.6, первой версии, включившей форматировщик.

Среды

Mix предоставляет концепцию «сред». Они позволяют разработчику настраивать компиляцию и другие параметры для конкретных сценариев. По умолчанию Mix понимает три среды:

  • :dev — та, в которой задачи Mix (например, compile) выполняются по умолчанию
  • :test — используется для mix test
  • :prod — та, которую вы будете использовать для запуска проекта в производстве

Среда применяется только к текущему проекту. Как мы увидим в последующих главах, любая зависимость, которую вы добавите в свой проект, по умолчанию будет выполняться в среде :prod.

Настройка по средам может быть выполнена путем доступа к Mix.env/0 в вашем файле mix.exs, который возвращает текущую среду в виде атома. Именно это мы использовали в параметрах :start_permanent:

def project do
  [
    ...,
    start_permanent: Mix.env() == :prod,
    ...
  ]
end

Если значение параметра :start_permanent равно true, ваше приложение запускается в постоянном режиме, что означает, что виртуальная машина Erlang (Erlang VM) завершится аварийно, если дерево управления приложения (supervision tree) завершит работу. Заметим, что такого поведения мы не хотим в средах разработки и тестирования, так как полезно поддерживать экземпляр VM в этих средах для целей отладки.

Mix по умолчанию будет использовать среду :dev, за исключением задачи test, которая будет по умолчанию использовать среду :test. Среду можно изменить с помощью переменной окружения MIX_ENV:

$ MIX_ENV=prod mix compile

Или в Windows:

> set "MIX_ENV=prod" && mix compile

Mix в производстве

Mix — это инструмент сборки, и, как таковой, он не должен использоваться в производственной среде. Поэтому рекомендуется обращаться к Mix.env/0 только в конфигурационных файлах и внутри mix.exs, а не в вашем коде приложения (lib).

Исследование

Mix имеет гораздо больше возможностей, и мы будем продолжать его изучать по мере создания нашего проекта. Обзор доступен в документации Mix, и вы всегда можете вызвать задачу help, чтобы увидеть все доступные задачи:

$ mix help
$ mix help compile

Теперь давайте перейдём к добавлению первых модулей и функций в наше приложение.

← Предыдущая страница Языки доменной специфики (DSL)
Следующая страница → Простое управление состоянием с агентами

Скачать версию ePub

Создано с помощью ExDoc (v0.34.1) для языка программирования Elixir

© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.17.2/introduction-to-mix.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API