Choreo.C4.Analysis (Choreo v0.9.0)

Copy Markdown View Source

Analysis functions for Choreo.C4 architecture models.

Provides validation and insight functions that answer practical questions about your C4 model:

  • Are there orphaned nodes with no relationships?
  • Are there containers or components without parents?
  • Which elements are missing descriptions or technology labels?
  • Is the model structurally consistent?

Further reading

Summary

Functions

Returns nodes with no connections (zero in-degree and out-degree).

Returns nodes that are missing a description.

Returns containers or components that have no parent.

Returns relationships that are missing a description label.

Returns containers and components that are missing a technology label.

Returns nodes that have children but no explicit relationships to/from them.

Validates a C4 model and returns a list of issues.

Functions

isolated_nodes(c4)

@spec isolated_nodes(Choreo.C4.t()) :: [Yog.node_id()]

Returns nodes with no connections (zero in-degree and out-degree).

Isolated elements in a C4 diagram are usually a mistake — either a missing relationship or an element that should be removed.

Examples

iex> c4 = Choreo.C4.new()
...>   |> Choreo.C4.add_person(:a)
...>   |> Choreo.C4.add_software_system(:b)
iex> Choreo.C4.Analysis.isolated_nodes(c4)
[:a, :b]

iex> c4 = Choreo.C4.new()
...>   |> Choreo.C4.add_person(:a)
...>   |> Choreo.C4.add_software_system(:b)
...>   |> Choreo.C4.add_relationship(:a, :b)
iex> Choreo.C4.Analysis.isolated_nodes(c4)
[]

This analysis answers the question: "Which elements have no relationships?"

missing_descriptions(c4)

@spec missing_descriptions(Choreo.C4.t()) :: [Yog.node_id()]

Returns nodes that are missing a description.

In C4, every element should have a meaningful description.

Examples

iex> c4 = Choreo.C4.new()
...>   |> Choreo.C4.add_person(:a, label: "A", description: "User A")
...>   |> Choreo.C4.add_software_system(:b, label: "B")
iex> Choreo.C4.Analysis.missing_descriptions(c4)
[:b]

This analysis answers the question: "Which elements lack descriptions?"

missing_parents(c4)

@spec missing_parents(Choreo.C4.t()) :: [Yog.node_id()]

Returns containers or components that have no parent.

In the C4 model every container should belong to a software system, and every component should belong to a container.

Examples

iex> c4 = Choreo.C4.new()
...>   |> Choreo.C4.add_container(:api, label: "API")
iex> Choreo.C4.Analysis.missing_parents(c4)
[:api]

iex> c4 = Choreo.C4.new()
...>   |> Choreo.C4.add_software_system(:banking)
...>   |> Choreo.C4.add_container(:api, parent: :banking)
iex> Choreo.C4.Analysis.missing_parents(c4)
[]

This analysis answers the question: "Which containers or components are missing a parent?"

missing_relationship_labels(c4)

@spec missing_relationship_labels(Choreo.C4.t()) :: [Yog.Multi.Graph.edge_id()]

Returns relationships that are missing a description label.

In C4, every relationship should describe how or what one element does with another.

Examples

iex> c4 = Choreo.C4.new()
...>   |> Choreo.C4.add_person(:a)
...>   |> Choreo.C4.add_software_system(:b)
...>   |> Choreo.C4.add_relationship(:a, :b, label: "Uses")
iex> Choreo.C4.Analysis.missing_relationship_labels(c4)
[]

This analysis answers the question: "Which relationships lack descriptions?"

missing_technology(c4)

@spec missing_technology(Choreo.C4.t()) :: [Yog.node_id()]

Returns containers and components that are missing a technology label.

In C4, containers and components should indicate the technology used.

Examples

iex> c4 = Choreo.C4.new()
...>   |> Choreo.C4.add_software_system(:banking)
...>   |> Choreo.C4.add_container(:api, technology: "Phoenix", parent: :banking)
...>   |> Choreo.C4.add_container(:db, parent: :banking)
iex> Choreo.C4.Analysis.missing_technology(c4)
[:db]

This analysis answers the question: "Which containers or components lack technology labels?"

parents_without_relationships(c4)

@spec parents_without_relationships(Choreo.C4.t()) :: [Yog.node_id()]

Returns nodes that have children but no explicit relationships to/from them.

A parent node (e.g. a software system) that has containers but no relationships to those containers may indicate an incomplete model.

Examples

iex> c4 = Choreo.C4.new()
...>   |> Choreo.C4.add_software_system(:banking)
...>   |> Choreo.C4.add_container(:api, parent: :banking)
iex> Choreo.C4.Analysis.parents_without_relationships(c4)
[:banking]

This analysis answers the question: "Which parent nodes have no relationships?"

validate(c4)

@spec validate(Choreo.C4.t()) :: [{:error | :warning, String.t()}]

Validates a C4 model and returns a list of issues.

Checks for:

  • isolated nodes (no relationships)
  • containers or components without parents
  • missing descriptions on any node
  • missing technology labels on containers and components
  • relationships without labels
  • orphaned parent nodes

Returns a list of {severity, message} tuples.

Examples

iex> c4 = Choreo.C4.new()
...>   |> Choreo.C4.add_person(:a, description: "User")
...>   |> Choreo.C4.add_software_system(:b, description: "System")
...>   |> Choreo.C4.add_relationship(:a, :b, label: "Uses")
iex> Choreo.C4.Analysis.validate(c4)
[]

iex> c4 = Choreo.C4.new()
...>   |> Choreo.C4.add_container(:api)
iex> issues = Choreo.C4.Analysis.validate(c4)
iex> Enum.any?(issues, fn {_sev, msg} -> String.contains?(msg, "parent") end)
true