Why does EK9 ban common names that every other language allows?
← Variable Naming Rules and Conventions · Ref: Q296
EK9 bans non-descriptive names because research links poor names to slower comprehension and lower-quality code, and real-world failures show what it costs when the meaning or limits of a value live only in someone's head.
THE RESEARCH EVIDENCE
Lawrie et al. (ICPC 2006) found full-word identifiers were understood better than single letters. Butler et al. (CSMR 2010) found flawed identifier names associated with code of lower quality. Hofmeister et al. (SANER 2017) found 72 professional developers located defects about 19% faster when identifiers were words rather than letters or abbreviations. Naming is a recurring subject of code review.
REAL-WORLD DISASTERS
Mars Climate Orbiter (1999): ground software reported impulse in pound-force seconds where newton-seconds were expected, and nothing in the data said which. Therac-25 (1985-87): a race condition, and a one-byte counter that wrapped to zero and skipped a safety check, led to six massive overdoses, at least three fatal. Toyota unintended acceleration (Bookout v. Toyota, 2013): the expert review found more than 10,000 global variables in the engine control software. Ariane 5 (1996): converting the horizontal-bias value BH from a 64-bit float to a 16-bit integer overflowed, on a range assumption the code did not state.
WHY OTHER LANGUAGES DO NOT DO THIS
Historical backward compatibility prevents Java, Python, and C++ from adding naming restrictions. The linter-based approach (Checkstyle, ESLint, pylint) treats naming as optional and configurable. The culture of minimal compiler enforcement assumes developers will self-police.
WHY EK9 CAN DO THIS
EK9 is a new language with no legacy codebases to break. The compiler is the right enforcement point because it cannot be misconfigured, skipped, or disabled. Every developer on every project gets the same naming quality.
THE PHILOSOPHY
Naming is not a style choice. It is a safety mechanism. Self-documenting code prevents bugs. The cost is 2 seconds of thought per variable. The benefit is code whose meaning does not live only in its author's head.
See Q290 for the banned list. See Q297 for a renaming guide. See Q144 for similar evidence-based design philosophy.
Example
#!ek9 defines module qa.naming.evidence defines function convertTemperature() as pure -> fahrenheitReading as Float <- celsiusReading as Float: (fahrenheitReading - 32.0) * 5.0 / 9.0 calculateFuelEfficiency() as pure -> distanceTravelled as Float fuelConsumed as Float <- kilometresPerLitre as Float: Float() if fuelConsumed > 0.0 kilometresPerLitre: distanceTravelled / fuelConsumed isWithinTolerance() as pure -> measuredPressure as Float targetPressure as Float tolerancePercent as Float <- withinRange as Boolean: false allowedDeviation <- targetPressure * (tolerancePercent / 100.0) lowerBound <- targetPressure - allowedDeviation upperBound <- targetPressure + allowedDeviation withinRange: measuredPressure >= lowerBound and measuredPressure <= upperBound defines program NamingEvidenceDemo() stdout <- Stdout() // === UNIT CLARITY: Prevents Mars Climate Orbiter-style failures === fahrenheitReading <- 212.0 celsiusReading <- convertTemperature(fahrenheitReading) stdout.println(`${fahrenheitReading}F = ${celsiusReading}C`) // === DESCRIPTIVE CALCULATIONS: No ambiguity about what is measured === distanceTravelled <- 450.0 fuelConsumed <- 35.0 kilometresPerLitre <- calculateFuelEfficiency(distanceTravelled, fuelConsumed) stdout.println(`Efficiency: ${kilometresPerLitre} km/L`) // === MEANINGFUL FLAGS: No generic flag variables === measuredPressure <- 14.5 targetPressure <- 14.7 tolerancePercent <- 5.0 pressureOk <- isWithinTolerance(measuredPressure, targetPressure, tolerancePercent) stdout.println(`Pressure within tolerance: ${pressureOk}`) // === EVERY NAME TELLS ITS STORY === sensorReadings <- [14.2, 14.5, 14.8, 15.1, 14.6] withinCount <- 0 for reading in sensorReadings if isWithinTolerance(reading, targetPressure, tolerancePercent) withinCount++ stdout.println(`${withinCount} of ${length sensorReadings} readings within tolerance`)
Common mistakes
E11031 — The name 'temp' is non-descriptive and banned. Using 'fahrenheitReading' prevents Mars Climate Orbiter-style unit confusion. See ek9 -h E11031 for details.
Incorrect:
temp <- 212.0 celsiusReading <- convertTemperature(temp) stdout.println(`${temp}F = ${celsiusReading}C`)
Correct:
fahrenheitReading <- 212.0 celsiusReading <- convertTemperature(fahrenheitReading) stdout.println(`${fahrenheitReading}F = ${celsiusReading}C`)
E11031 — The name 'flag' is non-descriptive and banned. Use a name like 'pressureOk' that describes what the boolean represents. See ek9 -h E11031 for details.
Incorrect:
flag <- isWithinTolerance(measuredPressure, targetPressure, tolerancePercent) stdout.println(`Pressure within tolerance: ${flag}`)
Correct:
pressureOk <- isWithinTolerance(measuredPressure, targetPressure, tolerancePercent) stdout.println(`Pressure within tolerance: ${pressureOk}`)
Other ways to ask this
- What evidence supports banning variable names like temp and data?
- Why is EK9 so strict about variable naming?
- What disasters were caused by poor variable naming?
Coming from another language?
Java: relies on Checkstyle, SonarQube, and code reviews for naming quality, all optional and configurable. Python: PEP 8 is advisory, linters like pylint flag poor names as warnings. Rust: clippy provides some naming guidance but nothing about descriptive quality. Go: golint is advisory, no enforcement of descriptive naming. C/C++: no naming enforcement, relies entirely on code reviews. Kotlin: detekt provides optional naming rules. JavaScript: ESLint can flag naming issues but rules are optional. EK9: compiler enforces descriptive naming at compile time based on research evidence, cannot be disabled or configured away.
Keywords: Mars, Therac, Toyota, ban, bug, convention, defect, disaster, evidence, identifier, migrate, naming, opinionated, philosophy, research, safety, why