Track
/
Elixir
Elixir
/
Esercizi
/
Ufficio comunale
Ufficio comunale

Ufficio comunale

Esercizio di apprendimento

Introduzione

Documentazione

In Elixir, la documentazione è un cittadino di prima classe.

Ci sono due attributi di modulo che si usano comunemente per documentare il codice: @moduledoc per documentare un modulo e @doc per documentare una funzione che segue l'attributo. L'attributo @moduledoc di solito compare sulla prima riga del modulo, mentre l'attributo @doc di solito compare subito prima della definizione di una funzione, o della specifica di tipo della funzione se ne ha una. La documentazione è comunemente scritta in una stringa multilinea usando la sintassi heredoc.

La documentazione di Elixir si scrive in Markdown.

defmodule String do
  @moduledoc """
  Strings in Elixir are UTF-8 encoded binaries.
  """

  @doc """
  Converts all characters in the given string to uppercase according to `mode`.

  ## Examples

      iex> String.upcase("abcd")
      "ABCD"

      iex> String.upcase("olá")
      "OLÁ"
  """
  def upcase(string, mode \\ :default)
end

Specifiche di tipo

Elixir è un linguaggio tipizzato dinamicamente, il che significa che non fornisce controlli di tipo in fase di compilazione. Le specifiche di tipo, però, si possono comunque usare come forma di documentazione.

Una specifica di tipo può essere aggiunta a una funzione usando l'attributo di modulo @spec subito prima della definizione della funzione. Dopo @spec vengono il nome della funzione e un elenco dei tipi di tutti i suoi argomenti, tra parentesi tonde e separati da virgole. Il tipo del valore restituito è separato dagli argomenti della funzione con un doppio due punti ::.

@spec longer_than?(String.t(), non_neg_integer()) :: boolean()
def longer_than?(string, length), do: String.length(string) > length

Tipi

I tipi usati più comunemente sono:

  • booleani: boolean()
  • stringhe: String.t()
  • numeri: integer(), non_neg_integer(), pos_integer(), float()
  • array: list()
  • un valore di qualsiasi tipo: any()

Alcuni tipi possono anche essere parametrizzati: ad esempio, list(integer) è un array di interi.

Anche i valori letterali possono essere usati come tipi.

Un'unione di tipi si può scrivere usando la barra verticale |. Ad esempio, integer() | :error significa un intero oppure l'atomo letterale :error.

Un elenco completo di tutti i tipi si trova nella sezione "Typespecs" della documentazione ufficiale.

Dare un nome agli argomenti

Anche agli argomenti di una specifica di tipo si può dare un nome, il che è utile per distinguere più argomenti dello stesso tipo. Il nome dell'argomento, seguito da un doppio due punti, va prima del tipo dell'argomento.

@spec to_hex({hue :: integer, saturation :: integer, lightness :: integer}) :: String.t()

Tipi personalizzati

Le specifiche di tipo non si limitano ai tipi predefiniti. I tipi personalizzati si possono definire usando l'attributo di modulo @type. La definizione di un tipo personalizzato inizia con il nome del tipo, seguito da un doppio due punti e poi dal tipo stesso.

@type color :: {hue :: integer, saturation :: integer, lightness :: integer}

@spec to_hex(color()) :: String.t()

Un tipo personalizzato può essere usato dallo stesso modulo in cui è definito, oppure da un altro modulo.

Istruzioni

Lavori all'ufficio comunale da un po' di tempo e hai sviluppato una serie di strumenti che velocizzano il tuo lavoro quotidiano, per esempio per compilare i moduli.

Ora sta per arrivare un nuovo collega e ti sei reso conto che i tuoi strumenti potrebbero non essere autoesplicativi. Nel tuo ufficio ci sono molte convenzioni strane, come compilare sempre i moduli con lettere maiuscole ed evitare di lasciare i campi vuoti.

Decidi di scrivere un po' di documentazione, così per il tuo nuovo collega sarà più facile iniziare subito a usare i tuoi strumenti.

1. Documenta lo scopo degli strumenti per i moduli

Aggiungi al modulo Form una documentazione che ne descriva lo scopo. Dovrebbe dire:

A collection of loosely related functions helpful for filling out various forms at the city office.

2. Documenta come compilare i campi con valori vuoti

Aggiungi documentazione e un typespec alla funzione Form.blanks/1. La documentazione dovrebbe dire:

Generates a string of a given length.

This string can be used to fill out a form field that is supposed to have no value.
Such fields cannot be left empty because a malicious third party could fill them out with false data.

Il typespec dovrebbe spiegare che la funzione accetta un solo argomento, un numero intero non negativo, e restituisce una stringa.

3. Documenta la suddivisione dei valori in array di lettere maiuscole

Aggiungi documentazione e un typespec alla funzione Form.letters/1. La documentazione dovrebbe dire:

Splits the string into a list of uppercase letters.

This is needed for form fields that don't offer a single input for the whole string,
but instead require splitting the string into a predefined number of single-letter inputs.

Il typespec dovrebbe spiegare che la funzione accetta un solo argomento, una stringa, e restituisce un array di stringhe.

4. Documenta come verificare se un valore entra in un campo con una lunghezza massima

Aggiungi documentazione e un typespec alla funzione Form.check_length/2. La documentazione dovrebbe dire:

Checks if the value has no more than the maximum allowed number of letters.

This is needed to check that the values of fields do not exceed the maximum allowed length.
It also tells you by how much the value exceeds the maximum.

Il typespec dovrebbe spiegare che la funzione accetta due argomenti, una stringa e un numero intero non negativo, e restituisce uno di due valori possibili. Restituisce o l'atomo :ok oppure una tupla di 2 elementi, dove il primo elemento è l'atomo :error e il secondo un numero intero positivo.

5. Documenta i diversi formati di indirizzo

Per qualche motivo a te ignoto, il sistema interno dell'ufficio comunale usa due modi diversi per rappresentare gli indirizzi: come mappa oppure come tupla.

Documenta questo fatto definendo tre tipi pubblici personalizzati:

  • address_map: una mappa con le chiavi :street, :postal_code e :city. Ogni chiave contiene un valore di tipo stringa.
  • address_tuple: una tupla con tre valori, street, postal_code e city. Ogni valore è di tipo stringa. Distingui i valori dando loro dei nomi nel typespec.
  • address: può essere un address_map o un address_tuple.

6. Documenta la formattazione dell'indirizzo

Aggiungi documentazione e un typespec alla funzione Form.format_address/1. La documentazione dovrebbe dire:

Formats the address as an uppercase multiline string.

Il typespec dovrebbe spiegare che la funzione accetta un argomento, un indirizzo, e restituisce una stringa.

Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Elixir Exercism

Vuoi iniziare Ufficio comunale?

Iscriviti a Exercism per imparare e padroneggiare Elixir con 58 concetti168 esercizi e il mentoring di persone reali, tutto gratis.