DEV Community

Cover image for Magic Numbers (in programming)
Anthony
Anthony

Posted on

Magic Numbers (in programming)

Today, I got feedback from a code review and learned something new. It was about "magic numbers", which are unique values with unexplained meaning or multiple occurrences which could (preferably) be replaced with named constants.

I've known about the concept of using constants rather than hard-coding values, but I didn't think of that for "magic number" situations. It's a pretty simple concept but I just wanted to share what I learned.

Magic Numbers are Bad

Magic numbers are language agnostic, but below, you'll see a code snippet in Java WITH magic numbers (the bad way).

class MagicNumber {

    String pipeDelimitedString = "This|is|an|example|of|Magic|Numbers|123 Parker Road|cityline@gmail.com";
    String [] splitString = pipeDelimitedString.split("\\|");

    obj.doSomething(splitString[7]);
    obj.doSomething(splitString[8]);           
}
Enter fullscreen mode Exit fullscreen mode

As you can see, I am simply splitting a pipe delimited string that contains some useful data (Home Address and Email Address).

splitString[7] refers to the 8th element, or 123 Parker Road, which is a Home Address

splitString[8] refers to the 9th element, or cityline@gmail.com, which is an Email Address

Why is that bad? We’ll it’s not easy to read.

splitString[n], where n is a number, may not mean anything from an outsider looking at your code. The numbers 7 & 8 have no meaning!

Now, you’ll see a code snippet in Java WITHOUT magic numbers (the good way).

class MagicNumber {

  String pipeDelimitedString = "This|is|an|example|of|Magic|Numbers|123 Parker Road|cityline@gmail.com";
  String [] splitString = pipeDelimitedString.split("\\|");

  obj.doSomething(splitString[Constants.HOME_ADDRESS]);
  obj.doSomething(splitString[Constants.EMAIL_ADDRESS]);           
}

class Constants {

  public static final int HOME_ADDRESS = 7;
  public static final int EMAIL_ADDRESS = 8;
}
Enter fullscreen mode Exit fullscreen mode

I’ve created a constants class, with some constants (HOME_ADDRESS = 7 and EMAIL_ADDRESS = 8).

Constants.HOME_ADDRESS & Constants.EMAIL_ADDRESS are much easier to understand and now have meaning!

If you aren’t convinced, what’s easier to read:
splitString[Constants.HOME_ADDRESS] or splitString[7]?

Again, this is just ONE example of magic numbers but there are many more. Thanks for reading!

Thanks for reading! Check out my blog for more articles like this @ www.anthonydellavecchia.com

Top comments (4)

Collapse
 
kfwerf profile image
Kenneth van der Werf

Interesting approach, why not just hide it in a method? Now you have a variable that doesn't make sense outside of a very specific constant thats public. E.g.

getHomeAddress(final String[] splitString) and getEmail(final String[] splitString), these should probably be private too as splitString would be specific.

Or just naming the variable? e.g. final var homeAddress = splitString[7], actually that would probably make more sense as the reusability is likely limited. Then the code to me is self documenting, e.g. 7 = home address as the var is named.

Collapse
 
anthonyjdella profile image
Anthony

@kfwerf Yea these also seem like great ideas! My post was one possible example but as you've shown, there are many other ways to do this. Thanks for brainstorming other ideas!

Collapse
 
scottshipp profile image
scottshipp • Edited

I also have found it helpful over the years to learn that many of the classic examples of "Magic Numbers" have their own domain-specific static values within utility classes in the standard library or a readily-available third-party library (like Apache Commons). A few examples:

Much of the time hard-coded math can be replaced with these utilities. For example, instead of calculating five minutes in milliseconds like:

long fiveMinutes = 300000;
Enter fullscreen mode Exit fullscreen mode

or (only slightly more comprehensible)

long fiveMinutes = 5 * 60 * 1000;
Enter fullscreen mode Exit fullscreen mode

Do it this way instead:

Duration.ofMinutes(5).toMillis()
Enter fullscreen mode Exit fullscreen mode
Collapse
 
anthonyjdella profile image
Anthony

@scottshipp Great points! Thanks for the examples!

Standard and third-party libraries might have common values (like the ones you mentioned). The cool thing with my example is that you can customize them yourself since a library won't know less common values (such as an address).