Написание документации
Elixir рассматривает документацию как первоклассный гражданин. Это означает, что документация должна быть легко написана и легко прочитана. В этом документе вы узнаете, как писать документацию на Elixir, охватывая такие конструкции, как атрибуты модулей, принципы стиля и doctests.
Markdown
Документация Elixir написана с использованием Markdown. В интернете есть множество руководств по Markdown, мы рекомендуем руководства, доступные на GitHub, как отправную точку:
Атрибуты модуля
Документация на Elixir обычно прикрепляется к атрибутам модулей. Давайте рассмотрим пример:
defmodule MyApp.Hello do
@moduledoc """
This is the Hello module.
"""
@moduledoc since: "1.0.0"
@doc """
Says hello to the given `name`.
Returns `:ok`.
## Examples
iex> MyApp.Hello.world(:john)
:ok
"""
@doc since: "1.3.0"
def world(name) do
IO.puts("hello #{name}")
end
end
Атрибут @moduledoc используется для добавления документации к модулю. @doc используется перед функцией для предоставления документации к ней. Помимо вышеуказанных атрибутов, @typedoc также может быть использован для прикрепления документации к типам, определённым в рамках типов спецификаций. Elixir также позволяет прикреплять метаданные к документации, передавая список ключевых слов атрибуту @doc и его аналогам.
Аргументы функции
При документировании функции имена аргументов выводятся компилятором. Например:
def size(%{size: size}) do
size
end
Компилятор выведет этот аргумент как map. Иногда вывод будет не оптимальным, особенно если функция содержит несколько разделов с соответствием аргумента на разных значениях каждый раз. Вы можете указать правильные имена для документации, объявив только заголовок функции в любой момент до реализации:
def size(map_with_size)
def size(%{size: size}) do
size
end
Метаданные документации
Elixir позволяет разработчикам прикреплять произвольные метаданные к документации. Это делается путем передачи списка ключевых слов соответствующему атрибуту (такому как @moduledoc, @typedoc, и @doc). Часто используемыми метаданными является :since, который отмечает, в какой версии был добавлен конкретный модуль, функция, тип или обратный вызов, как показано в примере выше.
Ещё одними распространёнными метаданными является :deprecated, который выводит предупреждение в документации, объясняя, что его использование не рекомендуется:
@doc deprecated: "Use Foo.bar/2 instead"
Обратите внимание, что ключ :deprecated не выдает предупреждение, когда разработчик вызывает функции. Если вы хотите, чтобы код также выдал предупреждение, вы можете использовать атрибут @deprecated:
@deprecated "Use Foo.bar/2 instead"
Метаданные могут иметь любой ключ. Инструменты документации часто используют метаданные, чтобы предоставить больше данных читателям и улучшить пользовательский опыт.
Рекомендации
При написании документации:
Сохраняйте первый абзац документации лаконичным и простым, обычно одной строкой. Инструменты, такие как ExDoc, используют первую строку для генерации сводки.
-
Ссылайтесь на модули по их полному имени.
Markdown использует обратные кавычки (
`) для цитирования кода. Elixir расширяет это, автоматически генерируя ссылки, когда ссылаются на имена модулей или функций. По этой причине всегда используйте полные имена модулей. Если у вас есть модуль, названныйMyApp.Hello, всегда ссылайтесь на него как на`MyApp.Hello`и никогда как на`Hello`. Ссылки на функции по имени и арности, если они локальны, как в
`world/1`, или по модулю, имени и арности, если указывают на внешний модуль:`MyApp.Hello.world/1`.Ссылки на
@callbackпутем добавления префиксаc:, как в`c:world/1`.Ссылки на
@typeпутем добавления префиксаt:, как в`t:values/0`.Начинайте новые разделы с заголовков второго уровня Markdown
##. Заголовки первого уровня зарезервированы для имен модулей и функций.Размещайте документацию перед первой инструкцией функций с несколькими инструкциями. Документация всегда относится к функции и арности, а не к каждому разделу.
Используйте ключ
:sinceв метаданных документации, чтобы отметить добавление новых функций или модулей в ваш API.
Doctests
Мы рекомендуем разработчикам включать примеры в свою документацию, часто под собственным заголовком ## Examples. Чтобы убедиться, что примеры не устаревают, тестовый фреймворк Elixir (ExUnit) предоставляет функцию под названием doctests, которая позволяет разработчикам тестировать примеры в своей документации. Doctests работают, анализируя фрагменты кода, начинающиеся с iex> из документации. Вы можете узнать больше об этом по адресу ExUnit.DocTest.
Обратите внимание, что doctests имеют ограничения. Когда невозможно выполнить doctest функции, поскольку она зависит от состояния или побочных эффектов, мы рекомендуем разработчикам включать примеры напрямую без приглашения iex>.
Документация != Комментарии к коду
Elixir рассматривает документацию и комментарии к коду как разные понятия. Документация — это явное соглашение между вами и пользователями вашего Application Programming Interface (API), будь то сторонние разработчики, коллеги или вы сами в будущем. Модули и функции должны быть документированы, если они являются частью вашего API.
Комментарии к коду предназначены для разработчиков, читающих код. Они полезны для отметки улучшений, оставления заметок (например, почему вы были вынуждены прибегнуть к обходному решению из-за ошибки в библиотеке) и т. д. Они привязаны к исходному коду: вы можете полностью переписать функцию и удалить все существующие комментарии к коду, и она продолжит работать так же, без изменений в поведении или документации.
Поскольку к закрытым функциям нет внешнего доступа, Elixir выдаст предупреждение, если закрытая функция имеет атрибут @doc и отбросит его содержимое. Однако вы можете добавить комментарии к коду в закрытые функции, как и к любому другому коду, и мы рекомендуем разработчикам делать это, когда считают, что это добавит полезной информации читателям и пользователям такого кода.
В заключение, будьте осторожны с избыточными комментариями к коду, такими как те, которые описывают то же самое, что и сам код:
# Total is the sum of the batch and individual entries total = batch_sum + individual_sum
Подводя итог, документация — это соглашение с пользователями вашего API, которые могут не иметь доступа к исходному коду; в то время как комментарии к коду предназначены для тех, кто взаимодействует непосредственно с исходным кодом. Вы можете выражать различные гарантии о своём программном обеспечении, разделяя эти два понятия.
Скрытие внутренних модулей и функций
Помимо модулей и функций, которые библиотеки предоставляют как часть своего публичного интерфейса, библиотеки также могут реализовывать важную функциональность, которая не входит в их API. Хотя к этим модулям и функциям можно получить доступ, они предназначены для внутреннего использования в библиотеке и, следовательно, не должны иметь документации для конечных пользователей.
Elixir позволяет разработчикам скрывать модули и функции из документации, устанавливая @doc false для скрытия конкретной функции или @moduledoc false для скрытия всего модуля. Если модуль скрыт, вы можете даже документировать функции в модуле, но сам модуль не будет отображаться в документации:
defmodule MyApp.Hidden do
@moduledoc false
@doc """
This function won't be listed in docs.
"""
def function_that_wont_be_listed_in_docs do
# ...
end
end
Если вы не хотите скрывать весь модуль, вы можете скрывать функции по отдельности:
defmodule MyApp.Sample do @doc false def add(a, b), do: a + b end
Однако помните, что @moduledoc false или @doc false не делают функцию закрытой. К функции выше по-прежнему можно обратиться как к MyApp.Sample.add(1, 2). Более того, если MyApp.Sample импортирован, функция add/2 также будет импортирована в вызывающую функцию. По этим причинам будьте осторожны при добавлении @doc false к функциям, вместо этого используйте один из этих двух вариантов:
Переместите недокументированную функцию в модуль со значением
@moduledoc false, как вMyApp.Hidden, чтобы предотвратить случайное открытие или импортирование функции. Помните, что вы можете использовать@moduledoc falseдля скрытия всего модуля и всё ещё документировать каждую функцию с помощью@doc. Инструменты по-прежнему проигнорируют модуль.Начните имя функции с одного или двух подчеркиваний, например,
__add__/2. Функции, начинающиеся с подчеркивания, автоматически обрабатываются как скрытые, хотя вы также можете быть явными и добавить@doc false. Компилятор не импортирует функции с ведущими подчеркиваниями, и они подсказывают любому, кто читает код, о предполагаемом частном использовании.
Code.fetch_docs/1
Elixir хранит документацию внутри предварительно определённых блоков в байткоде. К нему можно получить доступ из Elixir, используя функцию Code.fetch_docs/1. Это также означает, что к документации обращаются только при необходимости, а не при загрузке модулей виртуальной машиной. Единственный недостаток заключается в том, что модули, определённые в оперативной памяти, например, те, которые определены в IEx, не могут получить доступ к своей документации, так как их байткод не записывается на диск.
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.13.4/writing-documentation.html