Do you want to pick up from where you left of?
Take me there

Документация

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

Анотация

Колко коментари пишем и какво прави една документация добра, е доста спорен проблем в програмисткото общество. Въпреки това, всички можем да се съгласим, че документацията е важна, както за нас, така и за тези които работят с нашия код.

Elixir третира документацията като “гражданин първи клас“, предлагайка различни функции за достъп и генериране на документация за вашите проекти. Elixir ни дава много различни атрибути да анотираме кода. Нека погледнем тези три начина:

Инлайн документация

Вероятно най-лесния начин да коментариате вашия код е с инлайн коментари. Подобно на Ruby или Питон, инлайн коментарите на Elixir се означават с #, или още известен като “диес”.

# Outputs 'Hello, chum.' to the console.
IO.puts "Hello, " <> "chum."

Когато Elixir изпълнява този скрипт, ще игнорира всичко от # до края на реда, третирайки го като ненужни данни. Коментара не добавя нищо към операцията или изпълнението на скрипта, но когато не е толкова ясно, какво точно се случва, програмиста би трябвало да разбере, четейки от коментара ви. Внимавайте да не прекалявате със едно редовите коментари! Прекалено много коментари из кода, може да го направи труден за проследяване, за това е най-добре да се използва умерено.

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

Анотацията с @moduledoc позволява инлайн документация на модулно ниво. По принцип се поставя точно под defmodule декларацията в началото на файла. Долния пример показва коментар с @moduledoc декоратора.

defmodule Greeter do
  @moduledoc """
  Provides a function `hello/1` to greet a human
  """

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

Ние (или други) могат да достъпят тази документация, чрез помощната функция h в IEx.

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

iex> h Greeter

                Greeter

Provides a function hello/1 to greet a human

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

Както Elixir ни дава възможността за анотация на модули, също така предлага подобни анотации за документиране на функции. Анотацията с @doc позволява за инлайн документиране на функции и се поставято точно над функцията, която документира.

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

  @doc """
  Prints a hello message

  ## Parameters

    - name: String that represents the name of the person.

  ## Examples

      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)

Prints a hello message

Parameters

   name: String that represents the name of the person.

Examples

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

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

iex>

Забележете как може да използвате markup в нашата документация и терминала ще го покаже? Освен че е готино допълнение към екосистемата на Elixir, става много по-интересно, когато се обърнем към ExDoc, за генериране на HTML документация.

Бележка: aнотацията със @spec се използва, за статично анализиране на кода. <!– TODO: Remove this as a comment, once advanced/typespec is translated За да научите повече за нея, погледнете Спесификации и типове. –>

ExDoc

ExDoc е официален Elixir проект, който може да бъде намерен на GitHub. Той изкарва HTML (HyperText Markup Language) и онлайн документация за Elixir проект. Първо нека създадем Mix проект за нашата апликация:

$ mix new greet_everyone

* creating README.md
* creating .gitignore
* creating .formatter.exs
* 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)

Prints a hello message

Parameters

  • name: String that represents the name of the person.

Examples

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

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

Инсталация

Сега сме готови да настроим ExDoc. Добавете двата нужни пакета, в mix.exs файла, за да започнем.

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

only: :dev уточнява, че не искаме да се свалят и компилират тези пакети в production среда. Но защо Earmark? Earmark е Markdown парсър за Elixir, който се ползва от ExDoc, за обърне документацията в @moduledoc и @doc в HTML.

Важно е да се отбележи, че не сте задължени да ползвате Earmark. Може да го замените със други като Pandoc, Hoedown или Cmark; обаче ще се наложи да поконфигурирате малко повече, за което можете да прочетете тук. За този урок, ще се придържаме към Earmark.

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

В продължение, изпълнете следните две команди:

$ mix deps.get # gets ExDoc + Earmark.
$ mix docs # makes the documentation.

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

Ако всичко е минало по план, би трябвало да виждате подобно съобщение, като примера по-горе. Нека погледнем в нашия Mix проект и би трябвало да видим, че има друга директория doc/. Вътре е нашата генерирана документация. Ако отворим index страницата в нашия браузър, би трябвало да видим следното:

ExDoc Screenshot 1

Можем да видим, че Earmark е конвертирал нашия Markdown и ExDoc го показва в полезен формат.

ExDoc Screenshot 2

Сега можем да качим това в Github, нашият website, или HexDocs.

Най-добри практики

Тъй като Elixir е доста млад език, много стандарти все още се откриват докакто системата расте. Общността, обаче полага усилия за да затвърди най-добир практики. За да прочетете повече за тях вижте The Elixir Style Guide.

defmodule Greeter do
  @moduledoc """
  This is good documentation.
  """

end
defmodule Greeter do
  @moduledoc false

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

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

  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 """
  Prints a hello message

  ## Parameters

    - name: String that represents the name of the person.

  ## Examples

      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
Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!