ArchTest.Metrics (ArchTest v0.2.0)

Copy Markdown View Source

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

Summary

Functions

Returns the abstractness value for a single module or namespace.

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

Returns the instability value for a single module or namespace.

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

Types

metric_map()

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

Functions

abstractness(module_or_pattern, opts \\ [])

@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(module_or_pattern, opts \\ [])

@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(module_or_pattern, opts \\ [])

@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(pattern, opts \\ [])

@spec martin(
  String.t(),
  keyword()
) :: %{required(module()) => metric_map()}

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

Returns a map of module => metric_map.