If a constant value is given for an identifier, do not diminish the maintainability of the code in which it is used by assuming its value in expressions. Simply giving the constant a name is not enough to ensure modifiability; you must be careful to always use the name, and remember that the value can change.

Noncompliant Code Example

This noncompliant example first provides a constant value $BufferSize set to 512. This constant can later be used to buffer data read in from a file. But the code example defeats the purpose of defining $BufferSize as a constant by assuming its value in the subsequent expression:

our $BufferSize = 512;

# ...

my $nblocks = 1 + (($nbytes - 1) >> 9); # because $BufferSize = 512 = 2^9

The programmer might assume that everyone knows $BufferSize equals 512 and that right-shifting 9 bits is the same (for positive numbers) as dividing by 512. But if $BufferSize changes to 1024 on some systems, the subsequent expression must also be updated and can be overlooked easily. This makes modifications of constants difficult and error prone.

Compliant Solution

This compliant solution uses the identifier assigned to the constant value in the expression.

my $nblocks = 1 + (($nbytes - 1) / $BufferSize;

Risk Assessment

Assuming the value of an expression diminishes the maintainability of code and can produce unexpected behavior under any circumstances in which the constant changes.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

EXP03-PL

low

unlikely

medium

P2

L3

Automated Detection

Tool

Diagnostic

Perl::Critic

ValuesAndExpressions::ProhibitMagicNumbers

Related Guidelines

SEI CERT C Coding Standard

EXP07-C. Do not diminish the benefits of constants by assuming their values in expressions

SEI CERT C++ Coding Standard

VOID EXP07-CPP. Do not diminish the benefits of constants by assuming their values in expressions

Bibliography

[CPAN]Elliot Shank, Perl-Critic-1.116 ProhibitMagicNumbers
[Wall 2011]perlfunc