Class MetricLimits

java.lang.Object
org.ek9lang.compiler.support.MetricLimits

public final class MetricLimits extends Object
THE single source of truth for EK9's enforced complexity / coupling / cohesion / dependency-injection metric limits — the exact thresholds the phase-5 Acceptable*OrError checkers fire on. Use these; do NOT re-declare private static final int MAX_* inside a checker or an extractor.

Why this exists. These limits were previously duplicated: each checker held its own MAX_* constant, and at least one enquiry extractor (DiWiringExtractor.MAX_INJECTION_FIELDS) held a hand-copied mirror with a javadoc pointing back at the checker — a textbook DRY drift with no textual fingerprint to grep. Folding them here means (1) the checker and the MCP/IDE enquiry layer report the same number by construction, and (2) the enforced quality thresholds become discoverable — an AI can ask "what does EK9 enforce, at what value, per genus?" via ek9_query_metric_limits, which just serialises all().

Values and comparators are transcribed verbatim from the checkers (E11014-E11017, E11040, E11042, E11043). Genus tables and their exemptions live with the metric here; the two instance-level LCOM4 exemptions (built-in module, zero-field aggregate) are not genus metadata and remain in AcceptableCohesionOrError.

  • Field Details

    • MODULE_COUPLING

      public static final MetricLimit.ScalarLimit MODULE_COUPLING
      E11016 — module efferent coupling: distinct external modules a module depends on. Fires above 10.
    • CONSTRUCT_COUPLING

      public static final MetricLimit.GenusLimit CONSTRUCT_COUPLING
      E11015 — construct efferent coupling, per genus. Default (unlisted genera) is the class threshold.
    • LCOM4

      public static final MetricLimit.GenusLimit LCOM4
      E11014 — LCOM4 cohesion, per genus. Traits/records/functions are exempt (single body or intentionally independent operators). Default (unlisted genera) is the class threshold.
    • MODULE_COHESION

      public static final MetricLimit.CompoundLimit MODULE_COHESION
      E11017 — module cohesion: fires only when disconnected groups exceed BOTH an absolute cap (30) and a relative ratio (88% of constructs), and only once the module has at least 60 constructs.
    • MODULE_SIZE

      public static final MetricLimit.ScalarLimit MODULE_SIZE
      E11027 — declared constructs in a single module. Fires above 250.

      Deliberately generous: it is a god-module backstop, not a design nudge (module cohesion E11017 is the real design signal, and fires on unrelated constructs long before a count does). For calibration, 250 is roughly the 99th percentile of real-world Java packages and ~1.6x the largest module in EK9's own corpus; the JDK's own hand-written packages top out around 160.

      Counts SOURCE-DECLARED constructs only. Auto-generated monomorphised parameterised types (List of String and friends) are created in the module that declares the GENERIC, so counting them would let usage elsewhere inflate a module its author does not control - and would make the limit unhittable-by-design for any module exporting a generic. The count comes from ModuleCohesionTracker, which is populated from the parse tree, so synthesised types are excluded by construction rather than by a filter that could drift.

    • INJECTION_FIELDS

      public static final MetricLimit.ScalarLimit INJECTION_FIELDS
      E11040 — injected fields on a single component. Fires above 4 (Single Responsibility smell).
    • APP_REGISTRATIONS

      public static final MetricLimit.ScalarLimit APP_REGISTRATIONS
      E11042 — component registrations in a single application. Fires above 12.
    • INJECTED_TYPES_PER_METHOD

      public static final MetricLimit.ScalarLimit INJECTED_TYPES_PER_METHOD
      E11043 — distinct injected types used within a single method. Fires at or above 5 (last legal 4).
    • CALLABLE_COMPLEXITY

      public static final MetricLimit.ScalarLimit CALLABLE_COMPLEXITY
      E11010 — cyclomatic-style complexity of any callable construct (method / operator / function). Fires above 45.

      Enforced by AcceptableConstructComplexityOrError and re-used by AcceptableCombinedComplexitySizeOrError to normalise its complexity ratio — the two MUST agree for that ratio to mean anything.

    • TYPE_COMPLEXITY

      public static final MetricLimit.ScalarLimit TYPE_COMPLEXITY
      E11010 — aggregated complexity of a type (the sum of its members'). Deliberately large, so only a type accumulating very many even-moderately-complex methods trips it. Fires above 500.
    • COGNITIVE_COMPLEXITY

      public static final MetricLimit.ScalarLimit COGNITIVE_COMPLEXITY
      E11021 — cognitive complexity of a callable. Fires above 35, twice the industry standard of 15: high enough to accommodate genuinely hard code such as parsing, low enough that guarded code at depth 6 (42 points) is over the line.
    • NESTING_DEPTH

      public static final MetricLimit.ScalarLimit NESTING_DEPTH
      E11011 — nesting depth of control flow within a callable. Fires above 6.
    • INHERITANCE_DEPTH

      public static final MetricLimit.GenusLimit INHERITANCE_DEPTH
      E11019 — inheritance depth, per genus. Slightly stricter than the industry 5-6 because EK9 has by delegation as the alternative. Genera not listed are not depth-checked at all.
    • EXPRESSION_COMPLEXITY

      public static final MetricLimit.ScalarLimit EXPRESSION_COMPLEXITY
      E11013 — complexity of a single expression. Fires above 15, forcing intermediate variables.
    • STATEMENTS_OPERATOR

      public static final MetricLimit.ScalarLimit STATEMENTS_OPERATOR
      E11012 — statement budget for an operator. Operators should be single-purpose and brief.
    • STATEMENTS_METHOD

      public static final MetricLimit.ScalarLimit STATEMENTS_METHOD
      E11012 — statement budget for a method; class methods should have a focused responsibility.
    • STATEMENTS_FUNCTION

      public static final MetricLimit.ScalarLimit STATEMENTS_FUNCTION
      E11012 — statement budget for a function; a standalone unit can be somewhat larger.
    • STATEMENTS_SERVICE_OPERATION

      public static final MetricLimit.ScalarLimit STATEMENTS_SERVICE_OPERATION
      E11012 — statement budget for a service operation; a web operation of moderate complexity.
    • ARGUMENTS_PER_CALL

      public static final MetricLimit.ScalarLimit ARGUMENTS_PER_CALL
      E11010 — arguments in a single call. A hard stop, distinct from the 3- and 5-argument points further down that merely ADD to a complexity score rather than failing anything.
    • COMBINED_COMPLEXITY_SIZE

      public static final MetricLimit.RatioLimit COMBINED_COMPLEXITY_SIZE
      E11020 — complexity and size together. Neither operand is a gate on its own: the construct's complexity ratio times its statement ratio must exceed 0.50, so 70% of both passes and 72% of both does not. Expressed as a ratio because there is no count to compare against.
  • Method Details