Fork me on GitHub

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

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

Содержание

Аннотации

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

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

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

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

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

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

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

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

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

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

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

Увидеть эту документацию можно с помощью команды h из IEx.

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

iex> h Greeter

                Greeter

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

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

Функции можно документировать аналогично модулям. Это реализуется синтаксисом @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 .gitignore
* creating mix.exs
* creating config
* creating config/config.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 нужно добавить две зависимости: :earmark и :ex_doc.

  def deps do
    [{:earmark, "~> 0.1", only: :dev},
    {:ex_doc, "~> 0.11", only: :dev}]
  end

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

Стоит заметить, что использовать этот компонент не обязательно. Его можно заменить аналогами, такими так Pandoc, Hoedown или 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 прекратил нашу разметку, и теперь она отображается в отформатированном виде.

ExDoc Screenshot 2

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

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

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

defmodule Greeter do
  @moduledoc """
  Это хорошая документация.
  """

end
defmodule Greeter do
  @moduledoc false

end
defmodule Greeter do
  @moduledoc """
  ...
  В этом модуле есть функция `hello/1`.
  """

  def hello(name) do
    IO.puts "Hello, " <> name
  end
end
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
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

Поделиться