views:

3022

answers:

16

What is a magic number?

Why should it be avoided?

Are there cases where it's appropriate?

+8  A: 

A magic number is a sequence of characters at the start of a file format, or protocol exchange. This number serves as a sanity check.

Example: Open up any GIF file, you will see at the very start: GIF89. "GIF89" being the magic number.

Other programs can read the first few characters of a file and properly identify GIFs.

The danger is that random binary data can contain these same characters. But it is very unlikely.

As for protocol exchange, you can use it to quickly identify that the current 'message' that is being passed to you is corrupted or not valid.

Magic numbers are still useful.

Brian R. Bondy
I don't think that's the magic number he was refering to
Marcio Aguiar
Maybe you should remove the "file-format" and "networking" tags you added because he's clearly not talking about those kinds of magic numbers.
Landon
It's still very useful to know that magic numbers may refer to more than simply a code issue.-Adam
Adam Davis
If the subject read: "What is a magic number in terms of source code" then the tags shouldn't be there. But he did not specify this. So having my extra information is good. I think Kyle, Landon and Marcio are wrong.
Brian R. Bondy
There was also no way to determine which one he was looking for. Since I was the first post I couldn't guess which one he was looking for.
Brian R. Bondy
+11  A: 

Have you taken a look at the wikipedia entry for magic number?

It goes into a bit of detail about all of the ways the magic number reference is made. Here's a quote about magic number as a bad programming practice

The term magic number also refers to the bad programming practice of using numbers directly in source code without explanation. In most cases this makes programs harder to read, understand, and maintain. Although most guides make an exception for the numbers zero and one, it is a good idea to define all other numbers in code as named constants.

somas1
+2  A: 

I assume this is a response to my answer to your earlier question. In programming, a magic number is an embedded numerical constant that appears without explanation. If it appears in two distinct locations, it can lead to circumstances where one instance is changed and not another. For both these reasons, it's important to isolate and define the numerical constants outside the places where they're used.

Kyle Cronin
+34  A: 

A Magic Number is a hardcoded value that may change at a later stage, but that can be therefore hard to update.

For example, let's say you have a Page that displays the last 50 Orders in a "Your Orders" Overview Page. 50 is the Magic Number here, because it's not set through standard or convention, it's a number that you made up for reasons outlined in the spec.

Now, what you do is you have the 50 in different places - your SQL script (SELECT TOP 50 * FROM orders), your Website (Your Last 50 Orders), your order login (for i=0;i<50;i++) and possibly many other places.

Now, what happens when someone decides to change 50 to 25? or 75? or 153? You now have to replace the 50 in all the places, and you are very likely to miss it. Find/Replace may not work, because 50 may be used for other things, and blindly replacing 50 with 25 can have some other bad side effects (i.e. your Session.Timeout = 50 call, which is also set to 25 and users start reporting too frequent timeouts).

Also, the code can be hard to understand, i.e. "if a < 50 then bla" - if you encounter that in the middle of a complicated function, other developers who are not familiar with the code may ask themselves "WTF is 50???"

That's why it's best to have such ambigous and arbitary numbers in exactly 1 place - "const int NumOrdersToDisplay = 50", because that makes the code more readable ("if a < NumOrdersToDisplay", it also means you only need to change it in 1 well defined place.

Places where Magic Numbers are appropriate is everything that is defined through a standard, i.e. SmtpClient.DefaultPort = 25 or TCPPacketSize = whatever (not sure if that is standardized). Also, everything only defined within 1 function might be acceptable, but that depends on Context.

Michael Stum
Even if it can't change it's still a bad idea because it's not clear what's going on.
Loren Pechtel
+4  A: 

In programming, a "magic number" is a value that should be given a symbolic name, but was instead slipped into the code as a literal, usually in more than one place.

It's bad for the same reason SPOT (Single Point of Truth) is good: If you wanted to change this constant later, you would have to hunt through your code to find every instance. It is also bad because it might not be clear to other programmers what this number represents, hence the "magic".

People sometimes take magic number elimination further, by moving these constants into separate files to act as configuration. This is sometimes helpful, but can also create more complexity than it's worth.

Nick Retallack
Can you be more specific on why eliminating maginc numbers ISN'T alway good?
Marcio Aguiar
In math formulas likee^pi + 1 = 0
Jared Updike
I think he meant it isn't always good to move magic numbers to config files, which I agree.
Mike Stone
Marcio: When you do things like "const int EIGHT = 8;" and then requirements change and you end up with "const int EIGHT = 9;"
jmucchiello
Sorry, but that's simply an example of bad naming, or a base usage for the constant.
Tchalvak
+78  A: 

A magic number is a direct usage of a number in the code.

public class Foo {
     public void setPassword(String password) {
          // don't do this
          if (password.length() > 7) {
               throw new InvalidArgumentException("password");
          }  }

This should be refactored to:

public class Foo {
     public static final MAX_PASSWORD_SIZE = 7;

     public void setPassword(String password) {
          if (password.length() > MAX_PASSWORD_SIZE) {
               throw new InvalidArgumentException("password");
          } 
}

It improves readability of the code and it's easier to maintain. Imagine the case where I set the size of the password field in the GUI. If I use a magic number, whenever the max size changes, I have to change in two code locations. If I forget one, this will lead to inconsistencies.

The JDK is full of examples like in Integer, Character and Math classes.

PS.: Static analysis tools like FindBugs and PMD detects the use of magic numbers in your code and suggests the refactoring.

Marcio Aguiar
In the .NET world, FxCop and the Visual Studio 2008 code metrics should point these out for you.
paulwhit
So are they bad and if so why?
alchemical
0 and 1 are exceptions to this rule.
Jonathan Parker
Should I write: `public static final HUNDRED_PERCENTS = 100;` ?
Kirill V. Lyadvinsky
@Kirill: If you expect the definition of "Hundred Percents" to change, then yes. A better approach would be to have the variable from what it is to what it represents, i.e., public static final MAX_DOWNLOAD_PERCENTAGE = 100. Although even that wouldn't make sense, because "100 percent" is very well defined. On the other hand, the fact that Passwords can be a maximum of 7 characters long is not globally defined and actually differs, so that is a candidate for a variable.
Michael Stum
@Jonathan Parker, except when they're not (`TRUE`/`FALSE`)
Brendan Long
Just because a magic number will never change doesn't mean it shouldn't be replaced by a constant. My code is full of global constants like HzPerMHz and msecPerSecond. These will never change, but they make the meaning clearer, and provide some protection against typos.
Jeanne Pindar
A: 

@somas1 your quote said exactly what I was thinking. Any unexplained number besides 1 or 0 is a magic number. +1.

eed3si9n
+1  A: 

It is worth noting that sometimes you do want non-configurable "hard-coded" numbers in your code. There are a number of famous ones including 0x5F3759DF which is used in the optimized inverse square root algorithm.

In the rare cases where I find the need to use such Magic Numbers, I set them as a const in my code, and document why they are used, how they work, and where they came from.

Rob Rolnick
In my opinion, the magic number code smell refers specifically to *unexplained* constants. As long as you're putting them in a named constant, it shouldn't be a problem.
Don Kirkby
+1  A: 

@eed3si9n: I'd even suggest that '1' is a magic number. :-)

A principle that's related to magic numbers is that every fact your code deals with should be declared exactly once. If you use magic numbers in your code (such as the password length example that @marcio gave, you can easily end up duplicating that fact, and when your understand of that fact changes you've got a maintenance problem.

Andrew
IOW code should be written like this: `factorial n = if n == BASE_CASE then BASE_VALUE else n * factorial (n - RECURSION_INPUT_CHANGE); RECURSION_INPUT_CHANGE = 1; BASE_CASE = 0; BASE_VALUE = 1`
trinithis
+2  A: 

I've always used the term "magic number" differently, as an obscure value stored within a data structure which can be verified as a quick validity check. For example gzip files contain 0x1f8b08 as their first three bytes, Java class files start with 0xcafebabe, etc.

You often see magic numbers embedded in file formats, because files can be sent around rather promiscuously and lose any metadata about how they were created. However magic numbers are also sometimes used for in-memory data structures, like ioctl() calls.

A quick check of the magic number before processing the file or data structure allows one to signal errors early, rather than schlep all the way through potentially lengthy processing in order to announce that the input was complete balderdash.

DGentry
+4  A: 

A magic number can also be a number with special, hardcoded semantics. For example, I once saw a system where record IDs > 0 were treated normally, 0 itself was "new record", -1 was "this is the root" and -99 was "this was created in the root". 0 and -99 would cause the WebService to supply a new ID.

What's bad about this is that you're reusing a space (that of signed integers for record IDs) for special abilities. Maybe you'll never want to create a record with ID 0, or with a negative ID, but even if not, every person who looks either at the code or at the database might stumble on this and be confused at first. It goes without saying those special values weren't well-documented.

Arguably, 22, 7, -12 and 620 count as magic numbers, too. ;-)

Sören Kuklau
+11  A: 

It seems nobody mentioned a REALLY GOOD use of magic numbers...

I have found that there is 1 case where I PREFER magic numbers... and that is unit tests. In unit tests, you often want to construct and use your objects with data, and assert how that data was used and abused.

When you write your tests with "magic numbers" rather than factored constants, I feel it actually improves the quality of the tests... it often makes the tests a bit more clearer what they are doing, but more importantly makes the tests even more isolated.

With unit tests, you want each one to be isolated and independent of all the others. It should fail for exactly 1 reason, which does not depend on the usage or results of other tests. Thus, if you have magic numbers, you are implicitly tying all your tests to those magic numbers... unless you are defining constants like ZERO and ONE and TWO, which is less readable than just 0, 1 and 2.

In a test, I want to be able to see everything related to the test right there in the test itself, magic numbers and all.

This may be a subjective test style of mine by the way. In general though, magic numbers tend to be bad for all the reasons others have described.

Mike Stone
Very good remark!
Dimitri C.
+3  A: 

I've just been waiting for the right opportunity to do this.
Adam, thank you.

Sandman
More than happy to provide momentary amusement!
Adam Davis
+1  A: 

A problem that has not been mentioned with using magic numbers...

If you have very many of them, the odds are reasonably good that you have two different purposes that you're using magic numbers for, where the values happen to be the same.

And then, sure enough, you need to change the value... for only one purpose.

+1  A: 

What about initializing a variable at the top of the class with a default value? For example:

public class SomeClass {
    private int maxRows = 15000;
    ...
    // Inside another method
    for (int i = 0; i < maxRows; i++) {
        // Do something
    }

    public void setMaxRows(int maxRows) {
        this.maxRows = maxRows;
    }

    public int getMaxRows() {
        return this.maxRows;
    }

In this case, 15000 is a magic number (according to CheckStyles). To me, setting a default value is okay. I don't want to have to do:

private static final int DEFAULT_MAX_ROWS = 15000;
private int maxRows = DEFAULT_MAX_ROWS;

Does that make it more difficult to read? I never considered this until I installed CheckStyles.

Ascalonian
I think this would be okay if the constructor initializes the value. Otherwise if the value is initialized outside of the constructor, I just see it as a hassle and as something harder to read.
trinithis
A: 

What if I hardcode number while setting the parameters to PreparedStatement?

For e.g.

prepStatement.setString(1, "value1"); prepStatement.setString(2, "value2");

PMD highlights this as magic number, I don't it makes sense to make constants for 1, 2 as the value in constants will never change, I mean imagine final int ONE = 1; being changed later to final int ONE = 2...looks absurd.

rohit
I think you should submit this as a new question to Stackoverflow...
Adam Davis