Технологии отладки в Elixir

Отладку первых приложений на новом языке логично начинать с вывода значений в терминал. Для этого в Elixir можно воспользоваться функциями IO.puts/2 и IO.inspect/2. Но кроме этих способов отладки в Elixir существуют и другие.

В данной статье рассматриваются два из них — IEx.pry/0 и :debugger.

IEx.pry

Инструмент pry прекрасно знаком Ruby-разработчикам, однако в Elixir он ведёт себя по-другому. Чтобы увидеть это, создадим новый проект с помощью mix:

$ mix new example
$ cd example

Поместим в файл lib/example.ex следующий код:

require IEx;

defmodule Example do
  def double_sum(x, y) do
    IEx.pry
    hard_work(x, y)
  end

  defp hard_work(x, y) do
    2 * (x + y)
  end
end

Запустим новый сеанс в IEx и вызовем новую функцию:

$ iex -S mix
Interactive Elixir (1.2.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Example.double_sum(1, 2)

IEx.pry/0 работет на базе IEx. Хотя этот отладчик не предоставляет такие традиционные решения, как пошаговое исполнение, расстановка точек останова и т. п., он отлично подходит для проведения отладки в режимах разработки или тестирования. Он запускается в вызывающем процессе, блокируя его и предоставляя доступ к его переменным, лексической структуре и другой информации. Сеанс в pry можно завершить вызовом функции respawn, которая снова запустит IEx.

Elixir Pry

Узнать об этом подробнее можно в документации модуля.

Debugger

Если существует необходимость в использовании точек останова, то на помощь придёт модуль :debugger, встроенный в Erlang. Изменим пример так, чтобы он стал более наглядным:

defmodule Example do
  def double_sum(x, y) do
    hard_work(x, y)
  end

  defp hard_work(x, y) do
    x = 2 * x
    y = 2 * y

    x + y
  end
end

Теперь приступим к отладке:

$ iex -S mix
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Compiled lib/example.ex
Interactive Elixir (1.2.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :debugger.start()
{:ok, #PID<0.87.0>}
iex(2)> :int.ni(Example)
{:module, Example}
iex(3)> :int.break(Example, 3)
:ok
iex(4)> Example.double_sum(1,2)

Вместе с отладчиком запустится и графический интерфейс. Вызываем :int.ni(Example) для подготовки модуля к отладке, а затем ставим точку останова на третью строчку с помощью :int.break(Example, 3). Можно заметить, что после вызова функции статус процесса в отладчике изменился на «break»:

Debugger Elixir

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

В Debugger существуют и другие полезные возможности и команды. Подробнее об этом в документации модуля.

Устранение ошибок

При выполнении :int.ni(Example) в примере выше могут возникнуть ошибки:

iex(2)> :int.ni(Example)
** Invalid beam file or no abstract code: 'Elixir.Example'

Улучшенный алгоритм поиска исходных файлов, появился в Debugger только в новой 19 версии Erlang. Если же вы не используете последнюю версию Erlang, можно обновить debugger вручную, выполнив следующие действия.

  1. Загрузить файл int.erl из PR.

  2. Скомпилировать его с помощью erlc -o . int.erl.

  3. Заменить файл lib/debugger/ebin/int.beam в папке установки Erlang на новый скомпилированный файл.

© 2020 / Россия Любые мысли и вопросы пишите на elixir@wunsh.ru.