Magic Constants: Surprises And Frustrations

Magic constants are unexplained literals that magically appear in the middle of a source code, which are carefully placed by an evil programmer, to either indirectly brain f*ck their co-workers, or to simply give others a legal reason to shoot them in the head.

Here is an extreme example of using magic constants:

for (int i=0; i < 28731; i++){
  if (user[i].type.id == 56 && user[i].status == 4){
    // do something here
  }
  else if (user[i].type.id == 57 && user[i].status == 5){
    // do another here
  } 
}

At work, I encounter codes that are even more ridiculous than this one. Every single time I see codes with these sh*ts, I desperately wanted to find out who the f*ck wrote that code and put a handful of cockroaches inside his underwear while his hands and feet are tied together. You know, just to let him feel the horror and frustration I get every time I debug his code.

What the f*ck is this?!

The most famous and devastating form of Magic constants are these obscure numbers, also called Magic numbers. These are number literals that were not placed and used in their proper place in the code, or in other word hardcoded. Encountering just one magic number is enough to waste almost half of your hour, and sometimes half of your day. I'm not kidding you.

Who will ever put a number literal like 28731 in the middle of a code?! Without explanation! Without clues! f*ck you!

The rule of thumb is to use Named constants instead of Magic constants. Like this one:

int MAX_NUMBER_OF_USERS = 28731;  // named constant

for (int i=0; i < MAX_NUMBER_OF_USERS; i++){
...

Why?

Numbers are not expressive.
You can't just read a number literal and quickly comprehend its meaning. MAX_NUMBER_OF_USERS is undoubtedly much more expressive that 28731. The only reason that you will disagree to this is if you can't understand english or 28731 reminds you something from your childhood memories.

Change is difficult.
So you assign number 4 to user's status to indicate unverified accounts. But then your boss suddenly told you to use 0 instead of 4. After that, you realized that almost everywhere in your code you are checking unverified accounts using number 4. You need to find and change each of those lines bro. Now you're f*cked!

Another variant of Magic constants is the infamous Magic string. It looks friendlier than Magic numbers. But don't be fooled by the way it looks, it is still as dangerous as Magic numbers.

  if (choice == "Programming"){
    // do something
  }
  else if (choice == "Hacking"){
    // do something
  }

The code looks innocent and it seems that there is nothing wrong here. String literal is expressive indeed. However, changing the code is still difficult if you have these string literals all over the application. There are also other reasons:

Spelling mistakes cause silent errors.
What if you accidentally misspelled "Programming" and typed "Programing" instead? Your code will still compile and not a single f*ck will be given by the compiler. So you will feel that nothing is wrong. There is no syntax error, but actually there is a LOGICAL error lurking in the darkness of your code. But if you do it like this:

int PROGRAMMING = 1;  // named constant

if (choice == PROGRAMMING) {
 ...

If you misspelled the constant name, your compiler will raise an error and gracefully inform you about that.

Slow comparison.
It is slower to compare a string than an integer. It will take more CPU time to compare "THIS_IS_A_CONSTANT" than THIS_IS_A_CONSTANT, assuming that the latter is assigned to an integer.

String uses more memory than Integers.
Usually, integers are represented using 4 bytes. While string is represented 1 byte per character, depending on the encoding used. It means that "THIS_IS_A_CONSTANT" is represented by 18 bytes, while THIS_IS_A_CONSTANT uses only 4 bytes, again assuming that the latter is assigned to an integer.


When to use Magic Constants?

Don't worry, there are also acceptable situations where using Magic constants is not punishable by the cockroach-inside-your-undies torture.

Meaning is obvious on the current context.

float quarter_of(int number){
  return number / 4;
}

Here the use of the magic number 4 is obvious. There is no need to declare a named constant such as FOUR or DIVISOR. Stating the obvious is just a waste of time, so using a magic constant in this situation is okay.

fullName = first + " " + middle + " " + last;

On the second example, it is obvious that you are just putting spaces in the between the first, middle, and last name to have the full name. Don't ever think about assigning the whitespace character to a constant named SPACE!

1's and 0's can be hardcoded.
1's and 0's most of the time are already expressive enough. In situations where you are just incrementing a variable, you can just add 1 to it. No need to use a named constant such as ONE or INCREMENT_FACTOR. It is just obvious right? Zero can also immediately convey an empty, invalid, or initial value for something. It's just 1 and 0 are expressive enough for programmers. But still if 1 and 0 does not give obvious meaning in your code, it is still advisable to use named constants.

Using a known formula.
If your code uses a physics or just a simple arithmetic formula. You can just use the constants related to that formula. For instance converting Fahrenheit to Celsius, you can directly use the formula C = (F - 32) × 5/9. Although, leaving a comment as a reference on what formula you've used can be helpful in some instances.


Conclusion

Magic constants are frustrating and full of surprises. Seriously. Use it properly and moderately. The magic constants that you are using today may someday be the reason for you to pull your hair out while screaming pathetically. So use it wisely bro! Just imagine the feeling of having a cockroach party inside your undies, and you will never ever use magic constants the wrong way again.

cockroach

Imagine the horror! Oh sh*t!

>

6 Comments

  • Pats
    January 20, 2012 - 9:45 pm | Permalink

    Naalala ko tong magic constants na to nung nagbabasa ako ng ANSI C++ book =))

    wala lng nashare lng :D

  • chi
    January 20, 2012 - 11:12 pm | Permalink

    tol comment ko lang. sa ngayon parang sobrang bihira na ng hardcoded na number values. kadalasan ay strings na.

    yung practice namin sa team namin is we use Properties file. text file sya na may key/value pair mapping. then kapag ggamitin mo na sa java code mo, you can use the hardcoded key string directly kung saan lang sya kailangan IF doon mo lang sya gagamitin (not saying na good practice ‘to). pero pag more than one occurrence na, dinedeclare na yung key as a constant instance variable (private static final)

    • Karl Paragua
      January 20, 2012 - 11:22 pm | Permalink

      Yo men.

      Please don’t be offended, but I think you didn’t see enough codes. Like I said in the post, I saw absurd codes using Magic numbers in my line of work. We are doing maintenance works on big international sites, and I was surprised to see magic numbers scattered around the codes. I’m not kidding you. These companies are well-known but still hidden under their sites are these ugly magic numbers. The frustrations I got on working with those sites gave me the motivation to write this article, this is not just a topic that pops in to my mind.

      On the other hand, I agree on what you’ve said: If a string only occurred once, it is somehow safe to use a magic string.

      Thanks bro!

  • chi
    January 20, 2012 - 11:13 pm | Permalink

    ^sorry. nabanggit ko ang term na java.

    • Karl Paragua
      January 20, 2012 - 11:24 pm | Permalink

      Don’t worry, I’m not a Java hater anymore. HAHA :)

  • Rich
    September 13, 2012 - 7:40 pm | Permalink

    Don’t you just hate the use of magic numbers and strings??

    One thing about using named constants in your program is to improve it’s readability. Improve that and you improve it’s maintainability. You also don’t have to track down every occurance of ‘E’ in the program you’re modifying and hope that the ‘E’ you are changing is the correct ‘E’ that should be changed. Stick ‘E’ into a well named constant and the only place you have to change it is the constant.

    Using named constants is good programming practice. I’ve returned many a program to the programmer because it’s been full of magic numbers….. And don’t get me started on Global variables….

  • Creative Commons License
    This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.