Documentation, Formatting & Code Quality

28.1 Documentation

mix docs (ExDoc) generates HTML/EPUB. Published packages get docs on hexdocs.pm. Access in IEx: h MyLib.hello.

defmodule MyLib do
  @moduledoc """
  Utilities for **awesome** things.

  ## Examples

      iex> MyLib.hello()
      :world
  """

  @doc """
  Says hello. Returns `:world`.
  """
  @doc since: "1.1.0"
  @spec hello() :: :world
  def hello, do: :world

  @doc false   # hide from docs
  def internal, do: :ok
end

28.2 Formatter

mix format — no style debates.

[inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"], line_length: 98,
 import_deps: [:ecto, :phoenix], plugins: [Phoenix.LiveView.HTMLFormatter]]

28.3 Static analysis

Credo (mix credo --strict): style & consistency.

Dialyxir: type discrepancies.

Sobelow: Phoenix security analysis.

mix_audit: vulnerable dependencies.

mix compile --warnings-as-errors in CI.

🧪 Part II Exercises

Write WordCount.count/1 returning a map of word frequencies (case-insensitive, punctuation removed).

Model a BankAccount struct with deposit/2, withdraw/2 returning {:ok, acc} / {:error, :insufficient_funds}.

Implement a Shape protocol with area/1 and perimeter/1 for Circle, Rectangle, Triangle structs.

Parse a CSV file with File.stream! into a list of maps (header row = keys).

Implement Enumerable for a binary tree struct.

Write a Storage behaviour with InMemory and File implementations; select via config.

Group a list of people by age decade using Enum.group_by/3.

Write a comprehension that generates all Pythagorean triples with sides ≤ 30.

Build an escript that counts lines/words/chars of files (like wc), using OptionParser.

Write full ExUnit tests (with doctests and a property test) for exercises 1–3.