Source Написание документации
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 также может использоваться для прикрепления документации к типам, определённым в рамках типовpec.
Аргументы функции
При документировании функции имена аргументов выводятся компилятором. Например:
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.
Документация ≠ Комментарии к коду
Elixir рассматривает документацию и комментарии к коду как разные понятия. Документация – это явное соглашение между вами и пользователями вашего API (Application Programming Interface), будь то сторонние разработчики, коллеги или ваше будущее «я». Модули и функции должны быть всегда документированы, если они являются частью вашего API.
Комментарии к коду предназначены для разработчиков, читающих код. Они полезны для маркировки улучшений, оставления заметок (например, почему вы прибегли к обходному пути из-за ошибки в библиотеке) и так далее. Они привязаны к исходному коду: вы можете полностью переписать функцию и удалить все существующие комментарии к коду, и она будет продолжать работать так же, без изменений ни в поведении, ни в документации.
Поскольку к закрытым функциям нельзя получить доступ извне, Elixir выведет предупреждение, если закрытая функция имеет атрибут @doc и отбросит его содержимое. Однако вы можете добавить комментарии к коду к закрытым функциям, как и к любому другому фрагменту кода, и мы рекомендуем разработчикам делать это всякий раз, когда они считают, что это добавит полезной информации для читателей и тех, кто поддерживает такой код.
Подводя итог, документация – это соглашение с пользователями вашего 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 хранит документацию внутри предопределённых блоков в байткоде. Документация не загружается в память при загрузке модулей, вместо этого её можно читать из байткода на диске с помощью функции Code.fetch_docs/1. Недостатком является то, что модули, определённые в памяти, такие как те, что определены в IEx, не могут иметь доступ к своей документации, поскольку они не записывают свой байт код на диск.
© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.18.1/writing-documentation.html