Metastatic.Analysis.Cohesion
(Metastatic v0.10.4)
View Source
Cohesion analysis for containers (modules/classes).
Measures how well the members (methods/functions) of a container work together. High cohesion indicates that members are closely related and work toward a common purpose, which is a desirable property in object-oriented design.
Supported Metrics
LCOM (Lack of Cohesion of Methods)
Measures the number of disjoint sets of methods. Lower is better.
- LCOM = 0: Perfect cohesion (all methods share state)
- LCOM > 0: Poor cohesion (methods form disconnected groups)
TCC (Tight Class Cohesion)
Ratio of directly connected method pairs. Range: 0.0-1.0, higher is better.
- TCC = 1.0: All methods directly share state
- TCC > 0.5: Good cohesion
- TCC < 0.3: Poor cohesion
LCC (Loose Class Cohesion)
Ratio of directly or indirectly connected method pairs. Range: 0.0-1.0.
- LCC >= TCC always
- High LCC but low TCC: Methods connected through intermediaries
Algorithm
- Extract all methods/functions from container
- For each method, identify which instance variables it accesses
- Build a connection graph between methods based on shared variables
- Calculate LCOM (number of disconnected components)
- Calculate TCC (direct connections / total possible pairs)
- Calculate LCC (transitive closure / total possible pairs)
Examples
# High cohesion - all methods use shared state
ast = {:container, :class, "BankAccount", %{}, [
{:function_def, :public, "deposit", ["amount"], %{},
{:augmented_assignment, :+, {:attribute_access, {:variable, "self"}, "balance"}, {:variable, "amount"}}},
{:function_def, :public, "withdraw", ["amount"], %{},
{:augmented_assignment, :-, {:attribute_access, {:variable, "self"}, "balance"}, {:variable, "amount"}}},
{:function_def, :public, "get_balance", [], %{},
{:attribute_access, {:variable, "self"}, "balance"}}
]}
doc = Document.new(ast, :python)
{:ok, result} = Cohesion.analyze(doc)
result.lcom # => 0 (perfect cohesion)
result.tcc # => 1.0 (all methods connected)
result.assessment # => :excellent
# Low cohesion - methods don't share state
ast = {:container, :class, "Utilities", %{}, [
{:function_def, :public, "format_date", ["date"], %{}, ...},
{:function_def, :public, "calculate_tax", ["amount"], %{}, ...},
{:function_def, :public, "send_email", ["to", "msg"], %{}, ...}
]}
{:ok, result} = Cohesion.analyze(doc)
result.lcom # => 3 (three disjoint methods)
result.tcc # => 0.0 (no shared state)
result.assessment # => :very_poor
Summary
Functions
Analyze cohesion of a container (module/class/namespace).
Analyze cohesion of a container (module/class/namespace).
Functions
@spec analyze(Metastatic.language(), term(), keyword()) :: {:ok, map()} | {:error, term()}
Analyze cohesion of a container (module/class/namespace).
Returns {:ok, result} if the AST contains a container, or {:error, reason} otherwise.
Examples
iex> ast = {:container, :class, "Calculator", %{}, [
...> {:function_def, :public, "add", ["x"], %{},
...> {:augmented_assignment, :+, {:attribute_access, {:variable, "self"}, "total"}, {:variable, "x"}}},
...> {:function_def, :public, "get_total", [], %{},
...> {:attribute_access, {:variable, "self"}, "total"}}
...> ]}
iex> doc = Metastatic.Document.new(ast, :python)
iex> {:ok, result} = Metastatic.Analysis.Cohesion.analyze(doc)
iex> result.lcom
0
iex> result.tcc
1.0
@spec analyze!(Metastatic.language(), term(), keyword()) :: map()
Analyze cohesion of a container (module/class/namespace).
Returns {:ok, result} if the AST contains a container, or {:error, reason} otherwise.
Examples
iex> ast = {:container, :class, "Calculator", %{}, [
...> {:function_def, :public, "add", ["x"], %{},
...> {:augmented_assignment, :+, {:attribute_access, {:variable, "self"}, "total"}, {:variable, "x"}}},
...> {:function_def, :public, "get_total", [], %{},
...> {:attribute_access, {:variable, "self"}, "total"}}
...> ]}
iex> doc = Metastatic.Document.new(ast, :python)
iex> {:ok, result} = Metastatic.Analysis.Cohesion.analyze(doc)
iex> result.lcom
0
iex> result.tcc
1.0Unlike not-banged version, this one either returns a result or raises