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]);
}
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;
}
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)
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)
andgetEmail(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.@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!
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:
Measuring time
Common numbers found in math
Calculating file size
Much of the time hard-coded math can be replaced with these utilities. For example, instead of calculating five minutes in milliseconds like:
or (only slightly more comprehensible)
Do it this way instead:
@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).