Fork me on GitHub

Dokumentowanie kodu

Some contents of this translation may be outdated.
Several major changes were applied to the original lesson since the last update.

Jak dokumentować kod Elixira.

Spis treści

Adnotacje

Nie ważne jak wiele komentarzy piszemy i jak dobra jest dokumentacja, to zawsze jej jakość będzie niewystarczająca. Pomimo to wszyscy wiemy, że dokumentacja jest istotna zarówno dla nas samych, jak i dla osób, które pracują lub będą pracować z naszym kodem.

Elixir traktuje dokumentację jako byt podstawowy (ang. first-class citizen), oferując zestaw funkcji pozwalających na generowanie i pracę z dokumentacją w projekcie. Elixir dostarcza wiele różnych rozwiązań na poziomie kodu do tworzenia dokumentacji. Przyjrzyjmy się trzem z nich:

Komentowanie kodu

Najprostszą metodą dokumentowania kodu są komentarze. Podobnie jak w Pythonie i Ruby, tak w Elixirze komentarz rozpoczyna się znakiem #, zwanym kratką albo hashem.

Popatrzymy na ten skrypt (greeting.exs):

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

Gdy go uruchomimy, Elixir zignoruje wszystko od znaku # aż do końca linii, traktując jako nieistotny i nieinterpretowany element. Komentarz nie ma żadnej wartości ani nie wpływa na szybkość wykonania kodu. Jednakże pozwala innym zrozumieć nasz kod. Tego rodzaju komentarze powinny być używane z umiarem, ponieważ w dużej liczbie zaśmiecają kod i zamiast pomagać, mogą przeszkadzać. Niektórzy programiści w ogóle nie uważają tego rodzaju komentarzy za przydatne.

Dokumentowanie modułów

Adnotacja @moduledoc służy do dokumentowania modułów. Zazwyczaj umieszcza się ją w linii poniżej deklaracji defmodule na górze pliku. Poniższy przykład ilustruje użycie @moduledoc.

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

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

Dostęp do dokumentacji modułu w IEx jest możliwy z pomocą polecenia h.

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

iex> h Greeter

                Greeter

Provides a function hello/1 to greet a human

Dokumentowanie funkcji

Elixir poza adnotacją pozwalającą na dokumentowanie modułów ma też adnotację służącą do dokumentowania poszczególnych funkcji. Adnotacja @doc jest umieszczana nad dokumentowaną funkcją.

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

W IEx za pomocą polecenia h możemy też dostać się do dokumentacji funkcji.

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

iex> h Greeter.hello

                def hello(name)

`hello/1` 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>

Zauważ jak za pomocą znaczników, umożliwiliśmy terminalowi sformatowanie dokumentacji. Poza tym, że fajnie to wygląda i jest nowatorskim rozwiązaniem w ekosystemie Elixira, to daje nam duże możliwości przy generowaniu HTML-a z pomocą narzędzia ExDoc.

ExDoc

ExDoc jest oficjalnym projektem zespołu Elixira służącym do generowania HTML-a (HyperText Markup Language) i dokumentacji online dla projektów tworzonych w Elixirze, które można znaleźć na GitHub. Na początek stwórzmy nowy projekt w mix-ie:

$ 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

Następnie skopiujmy adnotację @doc do pliku lib/greeter.ex i upewnijmy się, że nadal działa on z linii poleceń. Jako że pracujemy z mixem uruchommy IEx korzystając z polecenia iex -S mix i wpiszmy:

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"

Instalacja

Wnioskując z powyższego komunikatu jesteśmy już gotowi by skonfigurować ExDoc. W pliku mix.exs musimy dodać dwie zależności :earmark i :ex_doc.

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

Podając opcję only: :dev mówimy mixowi, że nie chcemy pobierać i kompilować tych zależności na środowisku innym niż deweloperskie. Ale czym jest Earmark? Earmark jest to parser znaczników napisany dla Elixira, który służy ExDocowi na zamianę dokumentacji z adnotacji @moduledoc i @doc na elegancki kod HTML.

Oczywiście nie jesteśmy ograniczeni tylko do Earmarka. Jak chcesz możesz zamienić go na Pandoc, Hoedown albo Cmark; to wymaga trochę dodatkowej konfiguracji, o której poczytasz tutaj (ang.). Na potrzeby tej lekcji pozostaniemy jednak przy Earmarku.

Generowanie dokumentacji

Idąc dalej w linii poleceń wydajemy dwie komendy:

$ mix deps.get # pobiera ExDoc + Earmark.
$ mix docs # generuje dokumentację.

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

Jeżeli wszystko poszło zgodnie z planem powinieneś zobaczyć komunikat taki jak wyżej. Jeżeli zajrzymy teraz do naszego projektu to w katalogu doc/ odnajdziemy wygenerowaną dokumentację. Jeżeli otworzysz plik index.html w przeglądarce powinieneś zobaczyć:

ExDoc Screenshot 1

Jak widać Earmark stworzył z naszych znaczników dokumentację, a ExDoc wyświetla ją w czytelny sposób.

ExDoc Screenshot 2

Możemy ją teraz umieścić na GitHubie, naszej stronie, albo w serwisie HexDocs.

Dobre praktyki

Zasady tworzenia dokumentacji powinny być opisane w przewodniku dobrych praktyk języka. Jednakże Elixir jest jeszcze bardzo młodym językiem i wiele elementów jego ekosystemu musi zostać zestandaryzowanych, co oznacza, że dobre praktyki dla dokumentacji są tworzone przede wszystkim przez społeczność programistów. Można o tym poczytać, w dokumencie TheElixir 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

Podziel się