cohesion

package
v1.0.0-rc.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 13, 2026 License: Apache-2.0, Apache-2.0 Imports: 22 Imported by: 0

README

Cohesion Analysis

Preface

High cohesion and low coupling are the holy grails of software design. Cohesion measures how well the elements inside a module (like a class or function) belong together.

Problem

"God classes" or "God objects" are classes that do too much. They are hard to understand, hard to test, and hard to change. Low cohesion usually indicates that a class should be split into smaller, more focused classes.

How analyzer solves it

The Cohesion analyzer calculates the LCOM (Lack of Cohesion of Methods) metric (specifically LCOM4 variant) and other cohesion scores. It analyzes how methods in a class interact with the class's fields. If methods operate on disjoint sets of fields, the class likely lacks cohesion.

Historical context

LCOM metrics were introduced by Chidamber and Kemerer in 1994 as part of their object-oriented metrics suite. It has since been a standard metric in static analysis tools.

Real world examples

  • Refactoring Candidates: A high LCOM score flags classes that are likely doing too many unrelated things and should be refactored.
  • Architecture Review: Ensuring that core domain objects remain focused and cohesive.

How analyzer works here

  1. UAST Traversal: It uses Universal Abstract Syntax Trees (UAST) to parse code in a language-agnostic way.
  2. Function/Class Discovery: It identifies functions, methods, and classes.
  3. Variable Usage: For each method, it tracks which class variables (fields) are used.
  4. Graph Construction: It effectively builds a graph where methods are nodes and shared variable usage creates edges.
  5. Metrics:
    • LCOM4: Number of connected components in the graph.
    • Cohesion Score: A normalized score based on the density of connections.

Limitations

  • Static Analysis: It only looks at static usage. It cannot track dynamic field access (e.g., reflection).
  • Language Support: Relies on the quality of the UAST extraction for the specific language.

Further plans

  • Support for more granular cohesion metrics.
  • Visualization of the method-field usage graph.

Documentation

Overview

Package cohesion provides cohesion functionality.

Index

Constants

View Source
const (
	MetricDistExcellent = "excellent"
	MetricDistGood      = "good"
	MetricDistFair      = "fair"
	MetricDistPoor      = "poor"
)

MetricDist* constants are JSON-compatible distribution keys for metrics output.

View Source
const (
	CohesionThresholdExcellent = 0.6
	CohesionThresholdGood      = 0.4
	CohesionThresholdFair      = 0.3
)

Cohesion quality thresholds.

View Source
const (
	SectionTitle = "COHESION"

	// MetricTotalFunctions and related constants define metric labels.
	MetricTotalFunctions   = "Total Functions"
	MetricLCOM             = "LCOM Score"
	MetricCohesionScore    = "Cohesion Score"
	MetricFunctionCohesion = "Avg Cohesion"

	// DistExcellentMin and related constants define distribution thresholds for function cohesion.
	DistExcellentMin   = 0.6
	DistGoodMin        = 0.4
	DistFairMin        = 0.3
	DistLabelExcellent = "Excellent (>0.6)"
	DistLabelGood      = "Good (0.4-0.6)"
	DistLabelFair      = "Fair (0.3-0.4)"
	DistLabelPoor      = "Poor (<0.3)"

	// IssueSeverityFairMax and related constants define issue severity thresholds.
	IssueSeverityFairMax = 0.4
	IssueSeverityPoorMax = 0.3
	IssueValuePrefix     = "cohesion="

	// KeyTotalFunctions and related constants define report key names.
	KeyTotalFunctions   = "total_functions"
	KeyLCOM             = "lcom"
	KeyCohesionScore    = "cohesion_score"
	KeyFunctionCohesion = "function_cohesion"
	KeyMessage          = "message"
	KeyFunctions        = "functions"
	KeyFuncName         = "name"
	KeyFuncCohesion     = "cohesion"

	// DefaultStatusMessage is the default status message.
	DefaultStatusMessage = "No cohesion data available"
)

Section rendering constants.

View Source
const (
	MaxDepthValue = 10
)

MaxDepthValue is the default maximum UAST traversal depth for cohesion analysis.

Variables

View Source
var ErrInvalidFunctions = errors.New("invalid cohesion report: expected []map[string]any for functions")

ErrInvalidFunctions indicates the report doesn't contain expected functions data.

Functions

func RegisterPlotSections

func RegisterPlotSections()

RegisterPlotSections registers the cohesion plot section renderer with the analyze package.

Types

type AggregateData

type AggregateData struct {
	TotalFunctions   int     `json:"total_functions"   yaml:"total_functions"`
	LCOM             float64 `json:"lcom"              yaml:"lcom"`
	LCOMVariant      string  `json:"lcom_variant"      yaml:"lcom_variant"`
	CohesionScore    float64 `json:"cohesion_score"    yaml:"cohesion_score"`
	FunctionCohesion float64 `json:"function_cohesion" yaml:"function_cohesion"`
	HealthScore      float64 `json:"health_score"      yaml:"health_score"`
	Message          string  `json:"message"           yaml:"message"`
}

AggregateData contains summary statistics.

type AggregateMetric

type AggregateMetric struct {
	metrics.MetricMeta
}

AggregateMetric computes summary statistics.

func NewAggregateMetric

func NewAggregateMetric() *AggregateMetric

NewAggregateMetric creates the aggregate metric.

func (*AggregateMetric) Compute

func (m *AggregateMetric) Compute(input *ReportData) AggregateData

Compute calculates aggregate statistics.

type Aggregator

type Aggregator struct {
	*common.Aggregator
	common.PerFileRetainer
}

Aggregator aggregates results from multiple cohesion analyses.

func NewAggregator

func NewAggregator() *Aggregator

NewAggregator creates a new Aggregator.

func (*Aggregator) Aggregate

func (a *Aggregator) Aggregate(results map[string]analyze.Report)

Aggregate overrides the base Aggregate method to retain per-file reports.

type Analyzer

type Analyzer struct {
	// contains filtered or unexported fields
}

Analyzer performs cohesion analysis on UAST.

func NewAnalyzer

func NewAnalyzer() *Analyzer

NewAnalyzer creates a new Analyzer with generic components.

func (*Analyzer) Analyze

func (c *Analyzer) Analyze(root *node.Node) (analyze.Report, error)

Analyze performs cohesion analysis on the UAST.

func (*Analyzer) Configure

func (c *Analyzer) Configure(_ map[string]any) error

Configure configures the analyzer.

func (*Analyzer) CreateAggregator

func (c *Analyzer) CreateAggregator() analyze.ResultAggregator

CreateAggregator creates a new aggregator for cohesion analysis.

func (*Analyzer) CreateReportSection

func (c *Analyzer) CreateReportSection(report analyze.Report) analyze.ReportSection

CreateReportSection creates a ReportSection from report data.

func (*Analyzer) CreateVisitor

func (c *Analyzer) CreateVisitor() analyze.AnalysisVisitor

CreateVisitor creates a new visitor for cohesion analysis.

func (*Analyzer) Description

func (c *Analyzer) Description() string

Description returns the analyzer description.

func (*Analyzer) Descriptor

func (c *Analyzer) Descriptor() analyze.Descriptor

Descriptor returns stable analyzer metadata.

func (*Analyzer) Flag

func (c *Analyzer) Flag() string

Flag returns the CLI flag for the analyzer.

func (*Analyzer) FormatReport

func (c *Analyzer) FormatReport(report analyze.Report, w io.Writer) error

FormatReport formats the analysis report for display.

func (*Analyzer) FormatReportBinary

func (c *Analyzer) FormatReportBinary(report analyze.Report, w io.Writer) error

FormatReportBinary formats cohesion analysis results as binary envelope.

func (*Analyzer) FormatReportJSON

func (c *Analyzer) FormatReportJSON(report analyze.Report, w io.Writer) error

FormatReportJSON formats the analysis report as JSON.

func (*Analyzer) FormatReportPlot

func (c *Analyzer) FormatReportPlot(report analyze.Report, w io.Writer) error

FormatReportPlot generates an HTML plot visualization for cohesion analysis.

func (*Analyzer) FormatReportYAML

func (c *Analyzer) FormatReportYAML(report analyze.Report, w io.Writer) error

FormatReportYAML formats the analysis report as YAML.

func (*Analyzer) ListConfigurationOptions

func (c *Analyzer) ListConfigurationOptions() []pipeline.ConfigurationOption

ListConfigurationOptions returns the configuration options for the analyzer.

func (*Analyzer) Name

func (c *Analyzer) Name() string

Name returns the analyzer name.

func (*Analyzer) Thresholds

func (c *Analyzer) Thresholds() analyze.Thresholds

Thresholds returns the color-coded thresholds for cohesion metrics. LCOM-HS: lower is better (0 = perfect cohesion, 1 = no cohesion). Cohesion score and function cohesion: higher is better.

type ComputedMetrics

type ComputedMetrics struct {
	FunctionCohesion     []FunctionCohesionData    `json:"function_cohesion"      yaml:"function_cohesion"`
	Distribution         map[string]int            `json:"distribution"           yaml:"distribution"`
	LowCohesionFunctions []LowCohesionFunctionData `json:"low_cohesion_functions" yaml:"low_cohesion_functions"`
	Aggregate            AggregateData             `json:"aggregate"              yaml:"aggregate"`
}

ComputedMetrics holds all computed metric results for the cohesion analyzer.

func ComputeAllMetrics

func ComputeAllMetrics(report analyze.Report) (*ComputedMetrics, error)

ComputeAllMetrics runs all cohesion metrics and returns the results.

func (*ComputedMetrics) AnalyzerName

func (m *ComputedMetrics) AnalyzerName() string

AnalyzerName returns the name of the analyzer that produced these metrics.

func (*ComputedMetrics) ToJSON

func (m *ComputedMetrics) ToJSON() any

ToJSON returns the metrics in a format suitable for JSON marshaling.

func (*ComputedMetrics) ToYAML

func (m *ComputedMetrics) ToYAML() any

ToYAML returns the metrics in a format suitable for YAML marshaling.

type DistributionMetric

type DistributionMetric struct {
	metrics.MetricMeta
}

DistributionMetric computes cohesion distribution.

func NewDistributionMetric

func NewDistributionMetric() *DistributionMetric

NewDistributionMetric creates the distribution metric.

func (*DistributionMetric) Compute

func (m *DistributionMetric) Compute(input *ReportData) map[string]int

Compute calculates cohesion distribution.

type Function

type Function struct {
	Name      string
	Variables []string
	LineCount int
	Cohesion  float64
}

Function represents a function with its cohesion metrics.

type FunctionCohesionData

type FunctionCohesionData struct {
	Name         string  `json:"name"                  yaml:"name"`
	SourceFile   string  `json:"source_file,omitempty" yaml:"source_file,omitempty"`
	Language     string  `json:"language,omitempty"    yaml:"language,omitempty"`
	Directory    string  `json:"directory,omitempty"   yaml:"directory,omitempty"`
	Cohesion     float64 `json:"cohesion"              yaml:"cohesion"`
	QualityLevel string  `json:"quality_level"         yaml:"quality_level"`
}

FunctionCohesionData contains cohesion data for a function.

type FunctionCohesionMetric

type FunctionCohesionMetric struct {
	metrics.MetricMeta
}

FunctionCohesionMetric computes per-function cohesion data.

func NewFunctionCohesionMetric

func NewFunctionCohesionMetric() *FunctionCohesionMetric

NewFunctionCohesionMetric creates the function cohesion metric.

func (*FunctionCohesionMetric) Compute

Compute calculates function cohesion data.

type FunctionData

type FunctionData struct {
	Name       string
	SourceFile string
	Language   string
	Directory  string
	Cohesion   float64
}

FunctionData holds cohesion data for a single function.

type FunctionReportItem

type FunctionReportItem struct {
	Name               string
	CohesionAssessment string
	VariableAssessment string
	SizeAssessment     string
	LineCount          int
	VariableCount      int
	Cohesion           float64
}

FunctionReportItem is a typed representation of a per-function cohesion report item.

type LowCohesionFunctionData

type LowCohesionFunctionData struct {
	Name           string  `json:"name"                  yaml:"name"`
	SourceFile     string  `json:"source_file,omitempty" yaml:"source_file,omitempty"`
	Language       string  `json:"language,omitempty"    yaml:"language,omitempty"`
	Directory      string  `json:"directory,omitempty"   yaml:"directory,omitempty"`
	Cohesion       float64 `json:"cohesion"              yaml:"cohesion"`
	RiskLevel      string  `json:"risk_level"            yaml:"risk_level"`
	Recommendation string  `json:"recommendation"        yaml:"recommendation"`
}

LowCohesionFunctionData identifies functions with poor cohesion.

type LowCohesionFunctionMetric

type LowCohesionFunctionMetric struct {
	metrics.MetricMeta
}

LowCohesionFunctionMetric identifies functions needing attention.

func NewLowCohesionFunctionMetric

func NewLowCohesionFunctionMetric() *LowCohesionFunctionMetric

NewLowCohesionFunctionMetric creates the low cohesion metric.

func (*LowCohesionFunctionMetric) Compute

Compute identifies low cohesion functions.

type ReportData

type ReportData struct {
	TotalFunctions   int
	LCOM             float64
	CohesionScore    float64
	FunctionCohesion float64
	Functions        []FunctionData
	Message          string
}

ReportData is the parsed input data for cohesion metrics computation.

func ParseReportData

func ParseReportData(report analyze.Report) (*ReportData, error)

ParseReportData extracts ReportData from an analyzer report.

type ReportSection

type ReportSection struct {
	analyze.BaseReportSection
	// contains filtered or unexported fields
}

ReportSection implements analyze.ReportSection for cohesion analysis.

func NewReportSection

func NewReportSection(report analyze.Report) *ReportSection

NewReportSection creates a ReportSection from a cohesion report.

func (*ReportSection) AllIssues

func (s *ReportSection) AllIssues() []analyze.Issue

AllIssues returns all functions sorted by cohesion ascending (worst first).

func (*ReportSection) Distribution

func (s *ReportSection) Distribution() []analyze.DistributionItem

Distribution returns cohesion distribution categories.

func (*ReportSection) KeyMetrics

func (s *ReportSection) KeyMetrics() []analyze.Metric

KeyMetrics returns the key metrics for the cohesion section.

func (*ReportSection) TopIssues

func (s *ReportSection) TopIssues(n int) []analyze.Issue

TopIssues returns the top N functions with lowest cohesion.

type Visitor

type Visitor struct {
	// contains filtered or unexported fields
}

Visitor implements NodeVisitor for cohesion analysis.

func NewVisitor

func NewVisitor() *Visitor

NewVisitor creates a new Visitor.

func (*Visitor) GetReport

func (v *Visitor) GetReport() analyze.Report

GetReport returns the collected analysis report.

func (*Visitor) OnEnter

func (v *Visitor) OnEnter(n *node.Node, _ int)

OnEnter is called when entering a node during AST traversal.

func (*Visitor) OnExit

func (v *Visitor) OnExit(n *node.Node, _ int)

OnExit is called when exiting a node during AST traversal.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL