That some numbers are not magic would be obvious to a human reviewer, but the tool probably just treats any number in an expression as a magic number or something like that, and the workaround is to define constants for raw numbers. Which entirely defeats the purpose since now, people will just use these constants for actual magic numbers and the tool will see nothing.
But this is just 3 values in an expression and using a constant could actually be bad. Let's be a bit more practical.
int lightness(int r, int g, int b) { return (r+g+b)/3; }
Simple and straightforward int lightness(int r, int g, int b) {
const int NUMBER_ELEMENTS_AVERAGED = 3;
return (r+g+b)/NUMBER_ELEMENTS_AVERAGED;
}
Ok, I guess, but I think verbose for no good reason. But not as bad as the seemingly "cleaner" const int NUMBER_OF_COLOR_COMPONENTS = 3;
int lightness(int r, int g, int b) {
return (r+g+b)/NUMBER_OF_COLOR_COMPONENTS;
}
Imagine that you want want to add a color component, for example to support transparency (alpha). So you set NUMBER_OF_COLOR_COMPONENTS = 4, and then, your "lightness" function breaks, the simple (r+g+b)/3 would have stayed correct. That happened because didn't get the real meaning of that "3". Even if semantically, at the time you written that code, it is the number of color components, in reality, it is the number of terms in the expression. There is r, g, b: 3 terms, so 3. Who cares how many color components there are?Side note: I know it is the wrong formula for lightness, that's just an example.
You either have them on a list and calculate it dynamically based on the size, or have it as a magic number.
Say in some UI code called FooBarItem you suddenly have some call to set padding to 12. People will take this number, put it in constant and name it FOO_BAR_ITEM_PADDING = 12.
This is not better. It’s just jumping more through the code, and whatever is in the name of the constant is easily deductible from the usage pattern.
I learnt that pattern from others and nowadays I see it as useless. If you can add interesting info in the name or comments of the number, don’t bother extracting a constant.
Is it really difficult to see that these are pointless? If you actually think about what you are writing, that is.
const MILLIS_PER_SECOND = 1000;
...
...
...
...
...
const durationMs = MILLIS_PER_SECOND * duration
really clearer than
const durationMs = 1000 * duration
?
const duration_ms = 1000 * duration_s
And _us for microsec.
const duration_us = 1000 * duration_ms
But then the tool would probably reject my code for not following the naming conventions which ”disallows using underscores in variable names”.
Guess what I wanted to say is that there are always exceptions to the rule and there should always be some way to turn off the automatic checker for certain sections of the code.
long delay = (5 * 60 * 1000); // 5 minutes, in millseconds
And it's perfectly clear to me. Now, I think the comment is really helpful there (indicating intent), but I don't think having separate constants for each of the numbers there is going to make the code better. As it is, it's very easy to read at a glance, know what it's intended to do, and determine if it's correct (should you be worried about that at the moment). Which is what's important there.sleep(delay) always looks ok, but sleep(delayHours) is probably going to catch your eye as suspicious.
const duration = 1000 * duration