Документирование
Документирование кода на Elixir.
Аннотации
Что комментировать и что именно составляет качественную документацию - вечный спор в мире программирования. Однако, мы все можем согласиться с тем, что документация важна для нас и всех тех, кто работает с нашим кодом.
Elixir рассматривает документацию как важную часть языка, предоставляя различные функции для доступа и генерации документации для проектов. Ядро языка предоставляет несколько атрибутов для описания кода. Давайте рассмотрим три варианта:
-
#
- встроенная документация. -
@moduledoc
- документирование модуля. -
@doc
- документирование функции.
Встроенная документация
Самым простым вариантом для комментирования кода являются стандартные однострочные комментарии.
Похожие на аналоги в Ruby и Python, однострочные комментарии в Elixir начинаются с символа #
.
Рассмотрим этот скрипт (greeting.exs):
# Выводит 'Hello, chum.' в консоль.
IO.puts("Hello, " <> "chum.")
При запуске этого скрипта будет проигнорирован весь код от символа #
и до конца строки.
Этот код не оказывает никакого влияния на производительность скрипта, однако, из самого кода далеко не всегда понятно, что именно должен делать это код, поэтому следует оставить пояснения для программиста, который будет читать этот комментарий.
Но не следует засорять код подобными однострочными комментариями. Ситуация, когда в программе больше комментариев, чем строк кода, будет настоящим ночным кошмаром для многих.
Комментариями следует пользоваться сдержанно.
Документирование модулей
Вариант комментирования @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)
@spec hello(String.t()) :: String.t()
Печатает приветствие
Параметры
• name: Строка, в которой находится имя человека.
Примеры
iex> Greeter.hello("Sean")
"Hello, Sean"
iex> Greeter.hello("pete")
"Hello, pete"
iex>
Обратите внимание на то, что мы можем использовать разметку внутри нашей документации, и эту разметку отобразит наш терминал. Это действительно хорошо выглядит и прекрасно дополняет обширную экосистему языка Elixir. И использовать ExDox для генерации онлайн-документации гораздо приятнее, чем HTML.
Примечание: аннотация @spec
используется для статического анализа кода.
Подробнее о ней смотрите в уроке Спецификации и типы.
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)
@spec hello(String.t()) :: String.t()
Печатает приветствие
Параметры
• 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/. Внутри нее находится сгенерированная документация. Если открыть ее начальную страницу в браузере, то мы увидим следующее:
Мы видим, что Earmark обработал нашу разметку Markdown, и и теперь она отображается в удобном отформатированном виде.
Теперь мы можем разместить эту документацию на 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 lesson on GitHub!