# `ArchTest.Metrics`
[🔗](https://github.com/yoavgeva/arch_test/blob/v0.2.0/lib/arch_test/metrics.ex#L1)

Coupling and instability metrics for architecture analysis.

Implements Robert C. Martin's package metrics:

- **Afferent coupling (Ca)** — number of modules outside the package that
  depend on modules inside it. High Ca = the package is used a lot (stable).
- **Efferent coupling (Ce)** — number of modules inside the package that
  depend on modules outside it. High Ce = the package depends on many others.
- **Instability (I)** — `Ce / (Ca + Ce)`. Range: 0 (stable) to 1 (unstable).
- **Abstractness (A)** — ratio of abstract modules (behaviours, protocols)
  to total modules. Range: 0 to 1.
- **Distance from main sequence (D)** — `|A + I - 1|`. Ideal = 0.

## Usage

    # Per-module metrics for a namespace
    metrics = ArchTest.Metrics.martin("MyApp.**")
    # %{MyApp.Orders => %{instability: 0.6, abstractness: 0.0, distance: 0.4}, ...}

    # Single module coupling
    ArchTest.Metrics.coupling("MyApp.Orders")
    # %{afferent: 3, efferent: 7, instability: 0.7}

    # Assert on metrics
    assert ArchTest.Metrics.instability("MyApp.Orders") < 0.5

# `metric_map`

```elixir
@type metric_map() :: %{
  afferent: non_neg_integer(),
  efferent: non_neg_integer(),
  instability: float(),
  abstractness: float(),
  distance: float()
}
```

# `abstractness`

```elixir
@spec abstractness(
  String.t() | module(),
  keyword()
) :: float()
```

Returns the abstractness value for a single module or namespace.

Range: 0.0 (fully concrete) to 1.0 (fully abstract).

# `coupling`

```elixir
@spec coupling(
  String.t() | module(),
  keyword()
) :: metric_map()
```

Returns coupling metrics for the given module (or namespace root).

If a namespace pattern is given (e.g., `"MyApp.Orders"`), it computes
aggregate metrics treating all matching modules as a single package.

# `instability`

```elixir
@spec instability(
  String.t() | module(),
  keyword()
) :: float()
```

Returns the instability value for a single module or namespace.

Range: 0.0 (maximally stable) to 1.0 (maximally unstable).

# `martin`

```elixir
@spec martin(
  String.t(),
  keyword()
) :: %{required(module()) =&gt; metric_map()}
```

Computes Martin's package metrics for all modules matching `pattern`.

Returns a map of `module => metric_map`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
