Search documentation of Metastatic

# Metastatic.Analysis.Encapsulation (Metastatic v0.13.2)

View Source

Encapsulation analysis for containers (modules/classes).

Detects violations of encapsulation principles - the practice of hiding internal state and requiring all interaction to go through well-defined interfaces.

## Principles Checked

1. Information Hiding: Internal state should be private
2. Controlled Access: State access should go through methods
3. Interface Segregation: Public interface should be minimal and focused
4. Implementation Hiding: Internal details should not leak

## Detected Violations

### Public State (Critical)

Instance variables that are publicly accessible without getters/setters. Breaks encapsulation by allowing uncontrolled state modification.

### Missing Accessors (High)

Direct state access/modification without using accessor methods. Bypasses potential validation and business logic.

### Excessive Accessors (Medium)

Too many getter/setter pairs relative to behavior methods. May indicate a "data class" that lacks encapsulation of behavior.

### Leaky Abstraction (Medium)

Methods that expose internal implementation details. Makes refactoring difficult and couples clients to implementation.

## Examples

    # Good encapsulation
    ast = {:container, :class, "BankAccount", %{}, [
      {:function_def, :public, "deposit", ["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} = Encapsulation.analyze(doc)

    result.violations  # => []
    result.score       # => 100
    result.assessment  # => :excellent

    # Poor encapsulation - direct state access
    ast = {:container, :class, "User", %{}, [
      {:function_def, :public, "process", [], %{},
       {:assignment, {:attribute_access, {:variable, "self"}, "status"}, {:literal, :string, "done"}}}
    ]}

    {:ok, result} = Encapsulation.analyze(doc)
    result.violations  # => [%{type: :missing_accessor, ...}]
    result.assessment  # => :poor

## Summary

### Functions

analyze(doc)

Analyze encapsulation of a container (module/class/namespace).

analyze!(doc)

Analyze encapsulation of a container (module/class/namespace).

## Functions

# analyze(doc)

    @spec analyze(Metastatic.Document.t()) :: {:ok, term()} | {:error, term()}

Analyze encapsulation of a container (module/class/namespace).

Returns `{:ok, result}` if the AST contains a container, or `{:error, reason}` otherwise.

## Examples

    iex> ast = {:container, :class, "Example", %{}, [
    ...>   {:function_def, :public, "get_value", [], %{},
    ...>    {:attribute_access, {:variable, "self"}, "value"}}
    ...> ]}
    iex> doc = Metastatic.Document.new(ast, :python)
    iex> {:ok, result} = Metastatic.Analysis.Encapsulation.analyze(doc)
    iex> result.score
    100
    iex> result.assessment
    :excellent

# analyze!(doc)

    @spec analyze!(Metastatic.Document.t()) :: term()

Analyze encapsulation of a container (module/class/namespace).

Returns `{:ok, result}` if the AST contains a container, or `{:error, reason}` otherwise.

## Examples

    iex> ast = {:container, :class, "Example", %{}, [
    ...>   {:function_def, :public, "get_value", [], %{},
    ...>    {:attribute_access, {:variable, "self"}, "value"}}
    ...> ]}
    iex> doc = Metastatic.Document.new(ast, :python)
    iex> {:ok, result} = Metastatic.Analysis.Encapsulation.analyze(doc)
    iex> result.score
    100
    iex> result.assessment
    :excellent

Unlike not-banged version, this one either returns a result or raises