Why does EK9 reject a function whose complexity and size are both individually within limits?
← Code Quality · Ref: Q1339
EK9 checks complexity and statement count not only against their individual ceilings (E11010 for complexity, E11012 for statement count) but also against their COMBINATION. The combined score is (complexity / 45) x (statements / 150 for a function); if it exceeds 0.50 the compiler raises E11020 even though neither metric alone has broken its limit. A function at 73% complexity and 87% size scores 0.64 and fails. The fix is to decompose the one large branchy function into several small focused functions, each with low complexity and few statements, then compose them. This drives both ratios down so the product falls under 0.50. The research basis is NASA SATC work showing that modules which are both moderately complex AND moderately large have the lowest reliability.
See Q311 for the full list of quality checks and Q312 for how complexity is measured.
Example
defines module qa.quality.combined.complexity.size defines constant CODE_NEW <- 0 CODE_PAID <- 1 CODE_SHIPPED <- 2 defines function //THE FIX: small, focused functions keep BOTH complexity and statement //count low, so the combined (complexity/45) x (statements/150) score //stays well under the 0.50 threshold and E11020 never fires. classifyCode() as pure -> code as Integer <- level as String: "unknown" if code == CODE_NEW level: "new" else if code == CODE_PAID level: "paid" else if code == CODE_SHIPPED level: "shipped" describeCode() as pure -> level as String <- description as String: "no description" if level == "new" description: "awaiting payment" else if level == "paid" description: "ready to ship" else if level == "shipped" description: "in transit" formatReport() as pure -> level as String description as String <- report as String: `${level}: ${description}` //Composition function: trivial complexity, few statements. analyseOrder() as pure -> code as Integer <- report as String: "" level <- classifyCode(code) description <- describeCode(level) report: formatReport(level, description) defines program CombinedComplexitySizeDemo() stdout <- Stdout() codes <- [CODE_NEW, CODE_PAID, CODE_SHIPPED] for code in codes stdout.println(analyseOrder(code))
Other ways to ask this
- What triggers E11020 COMBINED_COMPLEXITY_SIZE?
- Why does EK9 fail a function that passes E11010 and E11012 separately?
- How do I fix a function that is both moderately complex and moderately large?
Coming from another language?
Java/Kotlin/Swift: the compiler never analyses the product of complexity and size; a method that is both moderately branchy and moderately long compiles silently and is only flagged later by optional tools (SonarQube, Detekt, SwiftLint) if a custom rule is configured, and even then as an advisory warning that can be suppressed. EK9 enforces the combined complexity-size threshold at compile time as a hard error (E11020), so the over-grown function simply will not build until it is decomposed.
Keywords: combined, E11012, quality, E11010, statements, complexity, E11020, decompose, size, maintainability