Magic Numbers Make Code Magical: Named Constants Are Boring
After 47 years of mass-producing bugs, I’ve come to love magic numbers. They add mystery and intrigue to your code. Named constants are just spoilers.
The Beauty of Mystery
Consider this elegant snippet:
def calculate_price(amount):
return amount * 1.0825 + 2.99 + (amount * 0.029 + 0.30) if amount > 50 else amount * 1.0825 + 4.99
What do these numbers mean? Nobody knows! That’s the magic. It’s like a treasure hunt for future developers.
Compare to the boring version:
TAX_RATE = 0.0825
SHIPPING_STANDARD = 4.99
SHIPPING_FREE_THRESHOLD = 50
SHIPPING_PREMIUM = 2.99
STRIPE_PERCENTAGE = 0.029
STRIPE_FIXED_FEE = 0.30
def calculate_price(amount):
tax = amount * TAX_RATE
shipping = SHIPPING_PREMIUM if amount > SHIPPING_FREE_THRESHOLD else SHIPPING_STANDARD
stripe_fee = amount * STRIPE_PERCENTAGE + STRIPE_FIXED_FEE
return amount + tax + shipping + stripe_fee
So many words! So much explanation! Where’s the fun in that?
The Constants Tax
| Named Constants | Magic Numbers |
|---|---|
| 10 extra lines | 0 extra lines |
| Everyone understands | Job security |
| Easy to change | Exciting to change |
| “Maintainable” | “Character building” |
| Boring | Magical |
As Dilbert’s Wally would say: “I’ve memorized all 47 magic numbers in our codebase. That makes me essential.”
Sacred Numbers
Some numbers are so universal they don’t need names:
// Everyone knows what these mean
if (status === 200) { } // HTTP OK
if (status === 404) { } // Not found
if (status === 418) { } // I'm a teapot
if (age >= 21) { } // Old enough (for something)
if (retries < 3) { } // Magic retry count
if (timeout > 30000) { } // Magic timeout
if (password.length >= 8) { } // Magic security
XKCD 221 shows us the beauty of magic numbers: return 4; // chosen by fair dice roll. guaranteed to be random.
The Named Constant Paradox
When you name a constant, you commit to a meaning. What if the meaning changes?
# 2024: Makes sense
MAX_RETRIES = 3
# 2025: Now we retry 5 times
MAX_RETRIES = 5 # MAX lies
# 2026: We retry forever
MAX_RETRIES = 999999 # MAX is meaningless
# Better: Use magic numbers, no lies
if retries < 3: # Then later...
if retries < 5: # Then later...
if retries < 999999: # Honest!
Magic numbers can’t lie because they make no promises.
Advanced: The Self-Documenting Magic Number
Add comments if you must, but keep the magic:
public double calculateInterest(double principal) {
return principal * 0.0375; // Trust me on this one
}
public int getMaxConnections() {
return 47; // Do not change. Ever. We tried.
}
public double getTimeout() {
return 3.14159; // Pi seconds seemed appropriate
}
The Maintenance Adventure
When requirements change, magic numbers create exciting adventures:
$ grep -r "86400" .
./payment.py: return days * 86400
./cache.py: timeout = 86400
./backup.py: seconds = 86400
./auth.py: expiry = 86400
./scheduler.py: interval = 86400
./logger.py: rotation = 86400
# Find and replace time!
# (Hope you don't miss any!)
This is called “active code maintenance.” It keeps developers engaged.
When Auditors Attack
If an auditor asks about a magic number, here’s your playbook:
- “That’s a business requirement from 2019”
- “Bob knew what it meant, but Bob left”
- “It’s based on complex calculations”
- “The tests pass, so it’s correct”
- “We’re planning to document that in Q4”
The Magic Number Collection
Every mature codebase has a collection:
// The Classics
waitMs(3000); // The standard wait
retry(5); // The retry count
buffer(4096); // The buffer size
limit(100); // The default limit
// The Mysterious
offset(37); // Discovered through trial and error
multiplier(2.718); // e, but nobody remembers why
threshold(420); // Nice
// The Legendary
MAGIC_CONSTANT = 0x5f3759df; // Fast inverse square root
Remember
Every named constant is just a magic number that lost its mystery. Keep your code interesting. Keep it magical.
As Dogbert once said: “I’ve obfuscated the financials using seventeen magic numbers. Even I don’t know what they mean anymore.”
The author’s codebase contains exactly 1337 magic numbers. He knows them all by heart.