A constant is almost definitely a MAGIC CONSTANT (or more commonly, a MAGIC NUMBER) if it has the following attributes:

  • is a constant non-variable, such as an integer or string literal
  • is arbitrary
  • appears in multiple places.

If the optional conditional characteristic (eg, does it appear in an if-then or loop statement?) is observed, it is guaranteeed to be a MAGIC CONSTANT. A magic constant is defined as a “non-defined constant” that is arbitrarily littered around the code base.

What is one potentially bad thing that could happen with a specific magic constant?

Pretend that a class, Currency, belongs to a standalone library. Pretend also that you are consuming it and have to catch the magic constant, “INSUFFICIENT FUNDS: Input is worth less than deliverable.” What happens if the creators arbitrarily decide to remove the “.” in the library? Your code no longer works, because it be compairing “INSUFFICIENT FUNDS: Input is worth less than deliverable” to “INSUFFICIENT FUNDS: Input is worth less than deliverable.” It will never be equal so the code will not be run.

Without unit tests, it would take a long time to figure out why this is, because no error would be thrown.

This is why magic constants should not be used.

Magic Constants in the Wild

However, you’ll see them all over the place:

// Fetch 10 rows
for ($a = 0; $a < 10; ++$a)

In the above example, 10 is the magic constant.

The Solution

The solution to magic constants is to make them REGULAR CONSTANTS.

define("NUM_ROWS", 10);
for ($a = 0; $a < NUM_ROWS; ++$a)

So in our example, we could do this:

 class CurrencyException
 { 
      const INSUFFICIENT_FUNDS = "INSUFFICIENT FUNDS: Input is worth less than deliverable.";
 }
 
 catch (CurrencyException $e)
 {
     if ($e->getMessage() == CurrencyException::INSUFFICIENT_FUNDS) { }
 }

That will always work, no matter what the creators change CurrencyExcetpion::INSUFFICIENT_FUNDS to.