Документирование

Это перевод актуальной версии оригинального урока.

Документирование кода на Elixir.

Содержание

Аннотации

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

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

  • # - встроенная документация.
  • @moduledoc - документирование модуля.
  • @doc - документирование функции.

Встроенная документация

Самым простым вариантом для комментирования кода являются стандартные однострочные комментарии. Похожие на аналоги в Ruby и Python, однострочные комментарии в Elixir начинаются с символа #.

Рассмотрим этот скрипт:

# Выводит 'Hello, chum.' в консоль.
IO.puts("Hello, " <> "chum.")

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

Документирование модулей

Вариант комментирования @moduledoc позволяет делать многострочную документацию на уровне модуля. Такие комментарии зачастую размещают под defmodule в самом начале файла. Пример ниже демонстрирует комментарий из одной строки внутри декоратора @moduledoc:

defmodule Greeter do
  @moduledoc """
  Включает в себя функцию `hello/1`, которая позволяет поздороваться с человеком.
  """

  def hello(name) do
    "Hello, " <> name
  end
end

Мы (и другие) можем просмотреть документацию этого модуля с помощью команды h в IEx. Мы можем в этом убедиться если сохраним наш модуль Greeter в новый файл greeter.ex и скомпилируем его:

iex> c("greeter.ex")
[Greeter]

iex> h Greeter

                Greeter

Включает в себя функцию `hello/1` для того чтобы поздороваться с человеком

Примечание: код выше является примером и в реальной жизни не обязательно вручную компилировать наши файлы как в этом примере если мы работаем в контексте Mix проекта. Вы можете использовать команду iex -s mix чтобы загрузить консоль IEx с текущим проектом если Вы работаете с Mix проектом.

Документирование функций

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

defmodule Greeter do
  @moduledoc """
  ...
  """

  @doc """
  Печатает приветствие

  ## Параметры

    - name: Строка, в которой находится имя человека.

  ## Примеры

      iex> Greeter.hello("Sean")
      "Hello, Sean"

      iex> Greeter.hello("pete")
      "Hello, pete"

  """
  @spec hello(String.t()) :: String.t()
  def hello(name) do
    "Hello, " <> name
  end
end

Если мы вернемся в IEx и попробуем снова воспользоваться командой h на полном имени функции, то увидим такое:

iex> c("greeter.ex")
[Greeter]

iex> h Greeter.hello

                def hello(name)

Печатает приветствие

Параметры

   name: Строка, в которой находится имя человека.

Примеры

    iex> Greeter.hello("Sean")
    "Hello, Sean"

    iex> Greeter.hello("pete")
    "Hello, pete"

iex>

Заметьте, что в этой документации можно использовать форматирование - и оно будет работать в консоли! Это не только круто, но и будет очень полезным, когда мы дойдем до генерирования HTML документации на лету с использованием ExDoc.

ExDoc

ExDoc - это официальный проект Elixir, который находится на GitHub. Он создает HTML (HyperText Markup Language) и онлайновую документацию. Для начала давайте создадим новый проект с помощью Mix:

$ mix new greet_everyone

* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/greet_everyone.ex
* creating test
* creating test/test_helper.exs
* creating test/greet_everyone_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

    cd greet_everyone
    mix test

Run "mix help" for more commands.

$ cd greet_everyone

Теперь давайте скопируем код из примера про @doc в файл с названием lib/greeter.ex и убедимся, что все еще работает из командной строки. Так как мы делаем это из Mix проекта, то запуск IEx делается немного по-другому - с использованием команды iex -S mix:

iex> h Greeter.hello

                def hello(name)

Печатает приветствие

Параметры

   name: Строка, в которой находится имя человека.

Примеры

    iex> Greeter.hello("Sean")
    "Hello, Sean"

    iex> Greeter.hello("pete")
    "Hello, pete"

Установка

Если все прошло нормально и вывод выше соответствует тому, что вы видите - можно устанавливать ExDoc. Внутри файла mix.exs нужно добавить :ex_doc.

def deps do
  [{:ex_doc, "~> 0.21", only: :dev, runtime: false}]
end

Мы передаем пару ключ-значение only: :dev, так как нам нужны эти зависимости только в процессе разработки. Но зачем нам Earmark?

ex_doc так же установит библиотеку Earmark.

Earmark - это инструмент для обработки Markdown для языка Elixir, который используется ExDoc для превращения нашей документации из блоков @moduledoc и @doc в красивый HTML.

Стоит заметить, что вы можете заметить инструмент обработки на Cmark если пожелаете, однако для этого вам нужно будет потратить немного времени на дополнительную настройку ExDoc, прочитать подробнее можно здесь. Для этого урока, мы остановимся на Earmark.

Генерация документации

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

$ mix deps.get # получит ExDoc + Earmark.
$ mix docs # создает саму документацию.

Docs successfully generated.
View them at "doc/index.html".

Если все прошло хорошо, то вы должны увидеть сообщение, похожее на вывод команды выше. Давайте теперь заглянем в Mix проект. Там должна появиться новая папка с названием doc/. Внутри нее находится сгенерированная документация. Если открыть ее начальную страницу ( doc/index.html ) в веб-обозревателе, то мы увидим следующее:

ExDoc Screenshot 1

Мы видим, что Earmark обработал нашу разметку Markdown, и и теперь она отображается в удобном отформатированном виде.

ExDoc Screenshot 2

Теперь мы можем разместить эту документацию на GitHub, на своем сайте, либо (наиболее обычный вариант) наHexDocs.

Лучшие практики документирования

Документация должна добавляться согласно правилам языка. Так как Elixir еще довольно молод, то многим стандартам еще предстоит появиться по мере того, как растет экосистема вокруг языка. Однако сообщество уже произвело первые наработки в этом направлении. Посетите The Elixir Style Guide что бы больше узнать об этом.

  • Всегда документируйте модули.
defmodule Greeter do
  @moduledoc """
  Это хорошая документация.
  """

end
  • Если вы не намерены документировать модуль, не оставляйте это поле пустым. Лучше установить значение false, например:
defmodule Greeter do
  @moduledoc false

end
  • При упоминании функций внутри документации используйте обратные кавычки:
defmodule Greeter do
  @moduledoc """
  ...
  В этом модуле есть функция `hello/1`.
  """

  def hello(name) do
    IO.puts("Hello, " <> name)
  end
end
  • Отделяйте код одной пустой строкой после @moduledoc:
defmodule Greeter do
  @moduledoc """
  ...

  This module also has a `hello/1` function.
  """

  alias Goodbye.bye_bye
  # and so on...

  def hello(name) do
    IO.puts("Hello, " <> name)
  end
end
  • Используйте разметку Markdown внутри документации. Это упрощаеи чтение этой документации в IEx или ExDoc.
defmodule Greeter do
  @moduledoc """
  ...
  """

  @doc """
  Печатает приветствие.

  ## Параметры

    - name: Строка, в которой содержится имя человека.

  ## Примеры

      iex> Greeter.hello("Sean")
      "Hello, Sean"

      iex> Greeter.hello("pete")
      "Hello, pete"

  """
  @spec hello(String.t()) :: String.t()
  def hello(name) do
    "Hello, " <> name
  end
end
  • Старайтесь включать примеры использования в вашу документацию. Это также позволит генерировать автоматические тесты из примеров кода, найденных в модуле, функции или макросе с помощью ExUnit.DocTest. Для этого нужно вызвать макрос doctest/1 из соответствующего теста и писать примеры согласно описанию, которое есть в официальной документации
Caught a mistake or want to contribute to the lesson? Edit this page on GitHub!