A 'magic number' is a literal value that appears in a program. For example: total = 1.08 * price; 1.08 is a magic number because it appears out of the blue, and it's unclear from this line of code what it means. It's generally better to replace magic numbers with NamedConstants, e.g. const double TAX_RATE_IN_TEXAS = 1.08; total = TAX_RATE_IN_TEXAS * price; This has a couple of advantages: * It results in better SelfDocumentingCode. In particular, the fuller name makes it clear that this code is banking on the assumption of only being applicable to one state. * If you change the value you only need to change the value once in the constant declaration. Relying on text editing tools to substitute '1.08' for something else would be brittle. * In statically-compiled languages, if the discount is removed entirely, the code will cease to compile until all mention of the discount has been removed (cf. Effective C++ by Scott Meyers [ISBN: 0-201-92488-9], Item 46). It also has one disadvantage: * Indirection. It will require you to hit * or Ctrl+] in vim to find the source of the information. This is generally true of abstraction, and is a burden even if it is worth the cost. The refactoring to remove the MagicNumber smell is ReplaceMagicNumberWithSymbolicConstant. ---- A pet peeve of mine is MagicNumber''''''s with inadequate explanation. Giving it a symbolic name is a good first step, but it isn't enough. Improving "if (allocation_count < 30)" to "if (allocation_count < MAX_ALLOCATIONS_BEFORE_REALLOCATION)" isn't enough. When we define const unsigned int MAX_ALLOCATIONS_BEFORE_REALLOCATION = 30; is the perfect place to add adequate explanation. In particular, I see 3 types of constants in programs: * particular numbers that must not be changed by later maintainers, or the program will not work right. In embedded system programming, often I have special values used for dealing with specific hardware at specific addresses (ideally the comment would point to the exact page of the data sheet from the manufacturer where these numbers came from). Other examples are physical and mathematical constants (pi, speed of light, transmission speed of ethernet cable, average distance from earth to moon, ...) (comment points to book or explains how it was measured). * particular numbers that are not simple to change. Numbers that were arbitrarily chosen at one time, but have been frozen into some communications protocol or data storage format -- changing the number means the "new" program can no longer communicate with, or read data from, "old" versions of the program. * particular numbers that later maintainers can change on a whim. Numbers that were arbitrarily chosen. For example, the number of branches from each node of a B* tree that is temporarily created and destroyed during a single run of the program. Ideally the comment would document what range of numbers the programmer feels would work fine, and which numbers were actually tested ("Using 30 works adequately", "I tried 5, 10, 20, 30, 40; all worked correctly, and 30 seemed the fastest"). Are there catchy WikiNames for these categories of numbers? -- DavidCary ---- Magic numbers aren't always obvious. If a number appears only once, then it might be okay to highlight it with a comment. Strings can also be treated as magic numbers. For example: list = "(" + val + "," + val2 + ")"; If you want to change "(" and ")" to, say, "{" and "}", then its better to write code like this: list = listStart + val + sep + val2 + listEnd; Here are a couple of rules for determining if a literal is a magic number: '''Strict Magic Number rule:''' Literals (including strings and characters) should only appear on the right hand side of a constant declaration statement. '''Practical Magic Number rule:''' A literal is a ''not'' a magic number if the most meaningful variable name for it is the same as the spoken name of the literal. '''ZeroOneInfinityRule:''' The only constants that should appear without a name in a program are 0 and 1, and then only if they are used in integer arithmetic or comparisons (that is, don't use the literals "0" and "1" as success/error codes or in other non-numeric ways). ''I don't know about this: computers seem to like the number 2 a lot, as well (but see TwoIsAnImpossibleNumber). It's a good target to shoot for, though.'' Can anyone give an example of a literal that is not magic via the Practical Magic Number rule, other than 0, 1, and -1? ''Probably things like OPEN_PAREN = "(", FOO_NAME = "foo.name", etc.'' In mathematics, sometimes a number is just a number. For instance, in the quadratic formula, (-b +/- sqrt(b^2 - 4ac)) / 2, the best names for 2 and 4 are TWO and FOUR. So they not practically magic. ''Certainly. However, such numbers should be contained within a function named Quadratic''''''Formula or somesuch, making intent clear. Just as if you had a constant that was precisely 3.14, you'd name it something so that a new developer would not mistake it for pi.'' ---- Apart from actual physical and mathematical constants (pi, e, the speed of light in a vacuum, etc. ''except that in applications that use these constants, the number of significant digits can be an issue, so they probably should still be defined'') it's usually best to read MagicNumber''''''s from a configuration file so that it is easier to change them. E.g. static final double DISCOUNT_PERCENT = getProperty( "sales.discount_percent" ); static final double DISCOUNT_FACTOR = 1 - (DISCOUNT_PERCENT / 100); // ... salePrice = DISCOUNT_FACTOR * regularPrice; ''Even for physical constants, this isn't a bad idea. There was this one time that I needed to eke just a tad more performance out of a program... a 2% boost to the speed of light, and I was set.'' ---- For time-related magic numbers it will often be clearer to break it down into an expression eg 60*60*24 instead of 86,400 ---- Also the first two bytes of a Un*x executable. See SheBang. Similarly, can refer to the first few bytes of a file or protocol unit. Readers of the file/unit can check the value to determine its format, or whether it has a valid format at all. See FileTypingSystem. ---- Try 'man magic' on a unix/linux box for more info ---- '''See Also:''' ZeroOneInfinityRule, TwoIsAnImpossibleNumber, NamedConstants. ---- CategoryMath