How does EK9 enforce complexity limits and what triggers E11010?

← Code Quality · Ref: Q696

EK9 measures cyclomatic complexity per function, method and operator, and also budgets the number of statements. Exceeding either limit triggers a compile error, forcing decomposition into smaller units.

CYCLOMATIC COMPLEXITY (E11010)

Each branch point (if, switch case, for, while, guard) adds to complexity. The compiler sets a threshold and rejects any function, method or operator that exceeds it. Methods in classes are checked individually and also raise E11010.

STATEMENT COUNT (E11012)

Separately, E11012 is a statement-count budget (for example 50 statements in an operator, 100 in a method, 150 in a function). A body with too many statements triggers E11012 even when its branching is simple.

STAYING WITHIN LIMITS

1. Decompose into smaller pure functions
2. Use guards to flatten nesting
3. Use switch instead of chained if/else
4. Extract complex conditions into named Boolean variables

FUNCTIONAL DECOMPOSITION

EK9 encourages extracting logic into small, focused pure functions:

  // Instead of one complex function:
  //   processOrder() with 20 branches
  // Use:
  //   validateOrder() + calculateTotal() + applyDiscount()

See Q316 for complexity metrics. See Q322 for quality enforcement. See Q310 for code quality overview.
See Q728 for nesting depth boundary. See Q733 for combined complexity boundary.

Example

defines module qa.codequality.complexitylimits

  defines constant

    LOW_THRESHOLD <- 10
    MEDIUM_THRESHOLD <- 50
    HIGH_THRESHOLD <- 90
    PASSING_SCORE <- 60

  defines function

    <?-
      Small focused function: low complexity.
      Single responsibility, easy to test.
    -?>
    classifyScore() as pure
      -> scoreValue as Integer
      <- classification as String: "average"

      if scoreValue < LOW_THRESHOLD
        classification: "very low"
      else if scoreValue < MEDIUM_THRESHOLD
        classification: "low"
      else if scoreValue < HIGH_THRESHOLD
        classification: "high"
      else
        classification: "very high"

    <?-
      Another small function: validates a single aspect.
    -?>
    isPassing() as pure
      -> scoreValue as Integer
      <- passing as Boolean: scoreValue >= PASSING_SCORE

    <?-
      Composing small functions keeps complexity low.
      Each function does one thing, combining them is straightforward.
    -?>
    generateReport() as pure
      -> scoreValue as Integer
      <- report as String: ""

      classification <- classifyScore(scoreValue)
      passed <- isPassing(scoreValue)

      if passed
        report: `${classification} (PASS)`
      else
        report: `${classification} (FAIL)`

  defines program

    ComplexityWithinLimitsDemo()
      stdout <- Stdout()

      scores <- [85, 42, 95, 15, 60]
      for scoreValue in scores
        stdout.println(generateReport(scoreValue))

Common mistakes

E50060 — String has no toUpperCase() method in EK9. Use upperCase() instead. See ek9 -h E50060 for details.

Incorrect:

stdout.println(generateReport(scoreValue).toUpperCase())

Correct:

stdout.println(generateReport(scoreValue))

E50060 — String has no toUpperCase() method in EK9. Use upperCase() instead. See ek9 -h E50060 for details.

Incorrect:

classification <- classifyScore(scoreValue).toUpperCase()

Correct:

classification <- classifyScore(scoreValue)
Other ways to ask this
  • What is E11010 cyclomatic complexity exceeded?
  • What is E11012 too many statements?
  • How do I keep functions within complexity limits?
  • What are the complexity thresholds in EK9?

Coming from another language?

Java: complexity checked by static analysis tools (optional). Python: no built-in check. C++: no built-in check. Rust: Clippy complexity warning (optional). Go: no built-in check. EK9: complexity is a compile error, not a warning.

Keywords: decomposition, E11010, limit, E11012, quality, threshold, metric, cyclomatic, clean-code, complexity