2

For example, does it make sense to refactor the following code:

a = a * 2;

as:

const int INT_TWO = 2;

// ...

a = a * INT_TWO;

My question hinges on the fact that the new constant conveys no extra meaning (as opposed to calling it, say, FOOBAR_FACTOR).

9
  • 7
    IMO, INT_TWO makes no sense (and you have to pray that it doesn't get 'refactored' into const int INT_TWO = 3;). FROBNICATION_FACTOR = 2 can make sense if that's what that 2 represents.
    – Mat
    Apr 15, 2020 at 16:08
  • 6
    I can't see any legitimate reason why you should refactor expressions by introducing meaninglessly named constants. A constant must surely have meaning, therefore a name should be selected which expresses that meaning.
    – Steve
    Apr 15, 2020 at 16:24
  • 3
    It doesn't make sense to use meaningless names for anything. a is just as meaningless a name as INT_TWO
    – mmathis
    Apr 15, 2020 at 16:29
  • 2
    Related: Are all magic numbers created the same?
    – Doc Brown
    Apr 15, 2020 at 17:10
  • 2
    I don't know why you would do this unless you're just spit balling stuff. You can start out with this while problem solving, but you should certainly refactor it to something meaningful. Meaningless names make future debugging extremely difficult.
    – WhyAyala
    Apr 15, 2020 at 19:26

2 Answers 2

18

No this is utterly pointless. Don't just extract literals to named constants without good reasons.

But do consider ways to explain why the a value has to be doubled in that context. That could involve:

  • a function name that explains the purpose of doubling, using terms from the problem domain. For example:

    function exponential_backoff(task, delay):
      while task() is not success:
        sleep(delay)
        delay = delay * 2
    
  • a comment explaining the reason for doubling

    // The backoff factor should increase the delay between retries.
    // A factor of at least two guarantees that the total load stays roughly constant
    // when the number of clients launching failing requests increases at a constant rate.
    delay = delay * 2
    
  • extracting the factor 2 to a constant or variable if it isn't obviously and necessarily always going to be 2.

    const BACKOFF_FACTOR = 2
    delay = delay * BACKOFF_FACTOR
    

The risk with naming variables or constants after themselves is that they might be changed in the future. For example:

const POINT_EIGHTEEN = 0.20  // actually a VAT rate but can't refactor
const TWO = 3

This is especially risky for constants that are extracted incidentally, and possibly have different meanings in different parts of the code. On the other hand, some constants are truly fixed and are not going to change, e.g. PI, KIBIBYTE = 1024, or SPACE = ' '. Apply your common sense to figure out what makes sense to name, and what doesn't.

6
  • What about Zero or Zero or Zero or One or MinusOne
    – JimmyJames
    Apr 22, 2020 at 17:44
  • @JimmyJames Many of those constants are superfluous, in my opinion. There's some justification for offering common values for objects like TimeSpan or BigInteger though. (a) The Zero TimeSpan is a good null object. (b) Constant pooling is good, but .NET can't fully do that when the classes have constructors. Ultra-common constants like zero or one are an adequate compromise.
    – amon
    Apr 22, 2020 at 20:49
  • Right which I think kind of puts a small qualifier on 'utterly pointless'. I think it's a lot better to have code like if value.equals(ZER0) than if value.equals(new BigInteger("0")) or similar. If we agree on that, then specifying your code continually checks to see if a BigInteger value is equivalent to 2, it seems rational to create a named constant for that even if there's no better name for 2 in that algorithm.
    – JimmyJames
    Apr 23, 2020 at 14:07
  • @JimmyJames In that example, if there is no meaningful name, I prefer new BigInteger(0) since it's clear immediately value is a BigInteger, not a byte or a float.
    – user949300
    May 2, 2020 at 0:28
  • @user949300 How would it be different for any named constant? Are you saying you would never use named constants for this reason?
    – JimmyJames
    May 4, 2020 at 15:30
9

Depends

If 2 has a meaning, like "number of pints on a quart", then yes. e g.

pints = quarts * PINTS_PER_QUART

So, the real question is, why are you multiplying a * 2? If giving 2 a meaningful name helps understand the code, you should do so.

1
  • 3
    His question was whether it makes sense to use meaningless constants, not meaningful ones.
    – Steve
    Apr 15, 2020 at 16:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.