# Code Quality: Formatter, Credo, Dialyzer and Types — Elixir & Phoenix

Source: https://www.geekswithgeeks.com/en/elixir-phoenix/s-quality

> Keep Elixir code consistent and catch bugs early with static analysis.

## Tools for maintainable Elixir

**`mix format`** formats code according to the community standard, configured in `.formatter.exs`, and `mix format --check-formatted` enforces it in CI. **Credo** is a static analysis tool that flags consistency issues, refactoring opportunities and likely bugs (`mix credo --strict`). **Dialyzer**, usually run through **dialyxir** (`mix dialyzer`), uses **`@spec`** typespecs and success typing to find type inconsistencies and unreachable code; it reports only what it can prove wrong, so it has no false positives in theory but can miss errors and its messages take practice to read. Elixir is also gaining a built-in **gradual, set-theoretic type system**: since version 1.17 the compiler performs type inference on patterns and guards and **warns about type violations**, such as calling a function with a value that can never match, without requiring annotations, with more capabilities arriving release by release. Other useful tools: **`mix xref`** for dependency graphs between modules, **Sobelow** for security scanning of Phoenix apps, **ex_doc** for documentation and **mix_audit** for vulnerable dependencies. A typical CI pipeline runs format check, compile with `--warnings-as-errors`, Credo, tests and Dialyzer.

## A CI quality pipeline

Formatting, warnings as errors, static analysis, tests and security checks.

```bash
# .github/workflows/ci.yml (steps excerpt, expressed as shell commands)
mix deps.get
mix format --check-formatted
mix compile --warnings-as-errors
mix credo --strict
mix test --warnings-as-errors
mix sobelow --config                 # Phoenix security checks
mix deps.audit                       # from the mix_audit package
mix dialyzer                         # cache the PLT files between CI runs

# typespecs help both Dialyzer and readers:
# @spec place_order(Customer.t(), map()) :: {:ok, Order.t()} | {:error, Ecto.Changeset.t() | atom()}
```

## Spellcheck, grammar check and a proofreader

The formatter is spellcheck for layout, Credo is a grammar checker with style advice, and Dialyzer plus the compiler's type checks are a careful proofreader who points out sentences that cannot possibly make sense.

**Quiz:** What does Dialyzer use to find bugs?

- [ ] Runtime logs
- [x] Typespecs and success typing to detect provable type inconsistencies
- [ ] Unit tests
- [ ] Code formatting rules

*Answer:* Typespecs and success typing to detect provable type inconsistencies. Dialyzer analyses types statically and reports definite contradictions.
