# Is every number in the code considered a “magic number”?

So every number in the code that we are sending to a method as an argument is considered as a Magic Number? To me, it shouldn't. I think if some number is let's say it is for minimum length of user name and we start using "6" in the code...then yeah we have a maintenance problem and here "6" is a magic number....but if we are calling a method that one of its arguments accept an integer for example as the ith member of a collection and then we pass "0" to that method call, in this case I don't see that "0" as a magic number. What do you think?

-
In your example, what does the 0 represent? – Aaron Kurtzhals Jan 8 '13 at 18:31
In the case you illustrate, that "0" has no magical properties whatsoever. – user61852 Jan 8 '13 at 20:21
Everything except 0,1 and 42 is magic – Mawg Dec 18 '14 at 14:02

If the meaning of the number is very clear in the context, I don't think it's a "magic number" problem.

Exmaple: Let's say you're trying to get the substring of a string, from the begining to some token and the code looks like this (imaginary language and library):

``````s := substring(big_string,0,findFirstOccurence(SOME_TOKEN,big_string));
``````

In this context, the meaning of the number 0 is clear enough. I suppose you could define `START_OF_SUBSTRING` and set it to 0, but in this case I think it would be overkill (although it would be the correct approach if you knew that the start of your substring might not be 0, but that depends on the specifics of your situation).

Another example might be if you are trying to determine if a number is even or odd. Writing:

``````isEven := x % 2;
``````

is not as strange as:

``````TWO := 2;
isEven := x % TWO;
``````

Testing negative numbers as

``````MINUS_ONE := -1;
isNegativeInt := i <= MINUS_ONE;
``````

also feels weird to me, I'd much rather see

``````isNegativeInt := i <= -1;
``````
-
To throw another example on there, in code where you're explicitly working with degrees on a circle, it would be fair to use a number such as `360` to mark a full rotation with the understanding that most people will know what that means (though this is a case where it wouldn't hurt to provide a constant) – KChaloux Jan 8 '13 at 19:00
KChaloux: If I could, I would -1 your comment. 360 is a magic number. If 360 happens to be a value for another constant, then you have 2 sets for 360 that are unrelated and indistinguishable. Junior comes along, go "That is a magic number", global search and replace 360 with "Degrees_in_Circle", run all unit and regression tests, all pass - delivers code fix. Code now a dogs breakfast, and we all know what happens to that after a short time....... – mattnz Jan 8 '13 at 20:17
@mattnz: Hopefully that kind of large-scale code change would be quickly caught (hopefully during code review, if they're that junior) long before it ever got into production. I think someone who would do that in that context would probably also replace `0` in the context of the my substring example. In which case, this might be the least amount of damage they can cause. It's been a long time since I did any coding that did geometric calculations, but generally, the values 15, 30, 45, 60, 90, 180, 360 were constants that were accepted. I've never seen anyone define `FIFTEEN_DEGREES`,... – FrustratedWithFormsDesigner Jan 8 '13 at 20:29
@KChaloux The example may actually fall apart if there's a shift from Degrees to Radians. By 360, you are expressing 1 complete rotation. Since there are multiple representations for the same value, it should be pulled out. Especially considering 360PI could look the same as 2PI (180 rotations but still pointing the same direction in the end), or 360 rotations the same as 1 rotation, but side effects may be different. – Chris Jan 8 '13 at 21:36
A bit of a straw man there, TWO and MINUS_ONE are utterly bad because replacing a magic number with its rendering in text is OF COURSE idiotic. The name of the constant has to convey its meaning. Except your examples are about fundamental facts about numbers, closely tied to just those specific numbers, so there isn't really any meaning beyond that. – Michael Borgwardt Jan 10 '13 at 16:15
``````bool hasApples = apples > 0;
``````

It is obvious zero means absence. I find 0 easier to understand than a variable named "absenceValue".

``````for(int i=0; i < arr.length; i++)
``````

It's obvious 0 is the starting position. I would be confused by a variable named "firstPosition". Such a variable would make me wonder if the starting position could change.

-

I would suggest three key factors in deciding whether something should be a constant declaration:

1. Is the number something that is precisely and concisely representable
2. Are there any plausible scenarios under which the value would have to change, but the code would not have to be rewritten
3. Would someone who sees the number be apt to recognize it more quickly or less quickly than someone who sees a named constant

Something like pi should probably be written as a named constant, rather than as a numeric literal, since a numeric literal is apt to be needlessly verbose, needlessly imprecise, or both. Something like the number of slots in a cache should likely be a named constant (though see note below) to allow for the possibility of expanding the cache without having to modify all the code that uses it. Things like the numbers "4", "28", and "29" in the statement `if ((year % 4)==0) FebruaryDays = 29; else FebruaryDays = 28;` should probably not be named constants, since the expression is almost certainly more readable than `if ((year % YearsBetweenLeapYears)==0) FebruaryDays = FebruaryDaysInLeapYear; else FebruaryDays = FebruaryDaysInNonLeapYear;`. Note that the maintainers of standards have indicated that the length of February 2100 in that year will not match the above formula, but I would recommend not handling that case unless it would be the only impediment to correctly handling such dates (i.e. the code won't get tripped by integer overflow or other such problems).

An important caveat with rule #2 is that in some cases code may rely upon hard-coded numbers in a way which cannot readily be represented by a named constant. For example, a method which computes a cross product of two vectors passed as discrete parameters will only be meaningful when used on three-dimensional vectors. The required number of dimensions is not a value that could meaningfully be changed without completely rewriting the routine. Even if one foresaw a possible need for computing the cross product of three 4-dimensional vectors, using a named constant for the value "3" would do little to make it easier to satisfy that need.

-

This, as all principles, is a matter of degree. Generally speaking, number literals in source code are more suspect the larger they are. A maximum length like 10 or a memory address like 0x587FB0 are obviously bad practice - it is almost certain that sooner or later you will have to repeat these values more than once, creating a risk of incompatibility and subtle errors introduced in places that weren't changed.

0 is at the other end of the scale; it is still suspect but not quite as much. Are you using 0 as a sentinel value? Then you should probably use a symbolic constant instead, just because the constant can explain what it means. Is it an extremely entrenched cultural agreement such as "0 means successful completion"? That's probably OK. Does it mean "the first item in a collection"? That may be harmless, but if there is an alternate method such as `first()` I'd probably prefer that.

-
"Are you using 0 as a sentinel value?" <-- Can you explain what you mean by "sentinel" here? I can't find a definition that seems to match. – roryap Nov 17 '15 at 15:08

Every unnamed number that's not immediately obvious from context is a magic number. Its a little silly to define numbers that have meaning that is immediately obvious from context.

In django (python web framework), I may define some database field with a raw number like:

``````firstname = models.CharField(max_length=40)
middlename = models.CharField(max_length=40)
lastname =  models.CharField(max_length=40)
``````

which is clearer (and the recommended practice ) than say

``````MAX_LENGTH_NAME = 40
...
firstname = models.CharField(max_length=MAX_LENGTH_NAME)
middlename = models.CharField(max_length=MAX_LENGTH_NAME)
lastname =  models.CharField(max_length=MAX_LENGTH_NAME)
``````

as I'm unlikely to ever need to change the length (and can always compare to the `max_length` of the field). If I do need to change the length of the field after initially deploying the application, I need to change it in exactly one location per field in my django code, and then additionally write a migration to change the schema of the DB. If I ever need to reference `max_length` of a defined field of a type of object, I can do it directly -- if those fields were defining a `Person` class, I can use `Person._meta.get_field('firstname').max_length` to obtain the `max_length` being used (which is defined in one place). The fact that the same 40 was used for multiple fields is irrelevant as I may want to change them independently. The length of firstname should never depend on the length of middlename or lastname; they are separate values and can change independently.

Often array indices can use unnamed numbers; like if I have a CSV file of data that I want to put in a python dictionary, with the first element in the row as the dictionary `key` I would write:

``````mydict = {}
mydict[row[0]] = row[1:]
``````

Sure I could name `index_column = 0` and do something like:

``````index_col = 0
mydict = {}
or worse define `after_index_col = index_col + 1` to get rid of the `index_col+1`, but that doesn't make the code clearer in my view. Also, if I give the `index_col` a name, I better make the code work even if the column is not 0 (hence the `row[:index_col] +` part).
Actually, `max_lngth=40` vs. `max_length=MAX_LENGTH_NAME` is a classic examlple of a magic number that screams to be a symbol. The day will come when you want to support 45 character names, and now every use of "40" is suspect and must be carefully examined. – Ross Patterson Jan 9 '13 at 0:21
@RossPatterson - This is not C where we constantly compare against a global var MAX_ARRAY_SIZE, but a decent web framework. The only place that the magic number comes up is where you declare the database model; everything else is compared against this value (e.g., 40 appears nowhere else in the code). Also note, you can't change this variable easily without doing schema migrations as its tied to a DB. If I wanted to change to say 1 character middle names its immediately obvious the one place to change in the code `40` to `1`. You have to think of context. – dr jimbob Jan 9 '13 at 7:33