How does EK9 detect magic literals?
← Code Quality · Ref: Q317
EK9 detects magic literals using a two-tier system. Magic literals are unnamed numeric or string values embedded directly in code. They obscure intent and make code harder to maintain.
TIER 1: COMPARISON LITERALS (E11064)
Any literal value used in a comparison is always flagged. Comparisons are decision points where the meaning of the value matters most. Instead of 'if age >= 18', use a named constant 'if age >= legalAdultAge'. This applies to ==, <>, <, >, <=, >=, and <=>, contains, and matches.
TIER 2: REPEATED LITERALS (E11065)
A literal that appears 3 or more times in the same file, or 4 or more times in the same module, is flagged. Repetition means the value has significance worth naming. Exempt from duplication checking: Boolean values, single characters, regular expressions, 0 and 1, and empty string.
CONSTANT ORGANISATION (E11066-E11067)
E11066: Constants should be defined in a dedicated constant block, not scattered through code.
E11067: Constant names should follow naming conventions (UPPER_CASE or descriptive camelCase).
EXEMPTIONS
The following contexts are exempt from magic literal detection: data definitions, fixture/test data, template output, and constant initialisation. This prevents false positives when defining legitimate data structures.
NAMED CONSTANTS PATTERN
Define meaningful names at the top of the function or in a constants block:
maximumRetries <- 3 timeoutSeconds <- 30 minimumPasswordLength <- 8
The name documents WHY this value was chosen.
See Q311 for the full quality checks catalog. See Q140 for defining constants. See Q141 for constant immutability.
Example
defines module qa.codequality.magic defines function <?- Demonstrates using named constants instead of magic literals. Every threshold has a meaningful name that documents its purpose. -?> classifyTemperature() as pure -> temperatureCelsius as Float <- classification as String: "moderate" freezingPoint <- 0.0 coldThreshold <- 10.0 hotThreshold <- 30.0 if temperatureCelsius <= freezingPoint classification: "freezing" else if temperatureCelsius <= coldThreshold classification: "cold" else if temperatureCelsius >= hotThreshold classification: "hot" <?- Named constants make password validation self-documenting. -?> isPasswordStrong() as pure -> password as String <- rtn as Boolean: false minimumLength <- 8 if length password >= minimumLength rtn: true defines program MagicLiteralsDemo() stdout <- Stdout() currentTemp <- 25.0 weatherReport <- classifyTemperature(currentTemp) stdout.println(`Temperature ${currentTemp}C is ${weatherReport}`) testPassword <- "SecurePass123" strongEnough <- isPasswordStrong(testPassword) stdout.println(`Password strong: ${strongEnough}`)
Common mistakes
E50001 — Renaming the variable means later references to 'weatherReport' become unresolved, triggering E50001. See ek9 -h E50001 for details.
Incorrect:
weatherReportXYZ <- classifyTemperature(currentTemp)
Correct:
weatherReport <- classifyTemperature(currentTemp)
E11064 — Using a raw literal 8 in a comparison is a magic literal. Name it minimumLength to document why this value was chosen. See ek9 -h E11064 for details.
Incorrect:
if length password >= 8
Correct:
minimumLength <- 8 if length password >= minimumLength
Other ways to ask this
- What are magic numbers in EK9?
- Why does EK9 reject literal values in comparisons?
- How do I fix E11064 magic literal error?
Coming from another language?
Java: SonarQube has MagicNumber rule but optional and configurable. Checkstyle MagicNumber only catches numerics, not strings. Rust: clippy has no magic number detection. Go: no magic number detection. Python: pylint has magic-value-comparison but optional. C++: no standard magic number detection. EK9: two-tier magic literal detection (comparison always, duplication 3+/file), mandatory compiler error, covers both numbers and strings.
Keywords: repeated, metric, E11065, E11064, comparison, value, constant, literal, number, clean-code, quality, named, magic