• Hanzito (unregistered)

    This is so much better.

    const decimalFormat = "%.4f"; const maxDecimalLength = 8;

    if (strlen(sprintf(decimalFormat, eventToValidate.Location.StartMilePoint.Value.toString)) > maxDecimalLength) { }

  • (nodebb)

    You might argue that's a distinction without difference, and you'd likely be right

    I'd argue that it's a difference without distinction, but yes.

  • (nodebb)

    Bonus points: This will throw an exception at runtime if the thread's CultureInfo doesn't use a period as its decimal separator.

  • Andrew (unregistered)

    "Anything but defining a constant. ANYTHING but that."

    Everybody keeps drinking the "global variables are evil" kool-aid, but some things are truly global. I'm going to assume that your pi is different from mine.

  • (nodebb)

    Much better to use a constant NINE_HUNDRED_NINETY_NINE_POINT_NINE_NINNE_NINE_NINE_NINE = "999.9999". Still a string of course, so as not to break anything.

  • Cole (unregistered)

    Assuming this is C#, using decimal.Parse every single time is bad for performance (ignoring the overhead of software based base-10 floating point). They should just use 999.999m.

  • John (unregistered)

    My guess is that they initially tried eventToValidate.Location.StartMilePoint.Value > 999.9999, but then the compiler complained about 999.9999 being double and they didn't know how to "fix" it. Hence decimal.Parse("999.9999").

  • (nodebb)

    Somehow one of my second semester programming students has escaped into the wild!

  • Brian (unregistered)

    Not only does someone not understand decimals, they're apparently not too keen on nullables either. Comparison operators on nullable types return false if either operand is null. So checking the HasValue and Value properties are redundant here.

  • OldCoder (unregistered) in reply to nerd4sale

    You are right.

    ALMOST_A_MILLION = 999.9999;

    is so much shorter.

  • (nodebb) in reply to Andrew
    Everybody keeps drinking the "global variables are evil" kool-aid, but some things are truly global. I'm going to assume that your pi is different from mine.

    Global variables are evil. Global constants are fine.

  • Sole Purpose Of Visit (unregistered) in reply to Dragnslcr

    I think that was rather the point.

    I've got a better one than this. My current codebase is littered with comparisons to 999999 ... sometimes 99999, or even 9999 ... on the grounds that this is a really large number that no comparison is ever going to exceed. (Nine is apparently the least lonely digit, according to Harry Nilsson.)

    It didn't seem to occur to anybody that uint.MaxValue would have been more appropriate in every single case.

  • (nodebb) in reply to Sole Purpose Of Visit

    I had some "fun" playing with long.MaxValue at one point: serializing that to JSON ended up with a slightly larger number for some reason (the last digits were 6000 instead of 5807), so deserializing it back into long would fail. The answer was to define an INFINITY constant of long.MaxValue / 10, along with the comment "let's be a bit more modest about infinity."

  • Martin (unregistered)

    I suppose management ordered that no magic numbers are allowed. But nobody mentioned magic strings..

  • (nodebb) in reply to Andrew

    My Pi is sweet cherry - you are stuck with Pecan [now that should start a flame war - please take to garage...]

    Seriously... GLOBAL constants are indeed evil. I have had times where different resolutions (accuracies) of PI were needed in different domains [the wonders of engineering and the real world]. Being able to keep the constant PI, in different namespaces made for much cleaner close than having to find different names at the global scope.

  • Worf (unregistered)

    Any reason it's 999.9999 rather than say, 1000? It's 1/10,000th shy, which if it was say, kilometers, we're talking about 10cm or so difference.

  • (nodebb)

    You laugh, but our code base contains constants

    ZERO
    ONE
    TWO
    THREE
    FOUR
    FIVE
    NEARLY_ZERO // about 1e-8
    

    Haven't really seen them in use though, but "no magic constants done wrong" is my best guess at explaining them.

    I've also come across an antipattern of copy-pasting constants from one namespace into another instead of refactoring into something both namespaces can import. And then using the same values as magic numbers in a third context anyway...

    Addendum 2023-02-03 03:23: Also:

    HALF
    QUARTER
    ONE_THIRD = ONE/THREE
    

    then various variants on PI times a factor.

    For some reason also the SQRT of various numbers.

    The rest thankfully have semantic naming.

  • Trev (unregistered) in reply to OldCoder

    I suppose it depends on the scale in use, but I feel nine hundred and ninety nine is a lot closer to a thousand than a million.

  • (nodebb) in reply to nerd4sale

    No, it it isn't.

    Constants should be named based on their meaning, not their values, so 2 constants like MAX_START_MP and MAX_STOP_MP would make sense whereas NINE_HUNDRED… doesn't.

    (Apart from that, any system that internally deals with numbers in terms of strings is guaranteed to be flawed -- there may be some practical reasons to allow that flaw to exist every now and then, e.g. when interfacing with stupid external libraries, but even such circumstances don't make it right).

  • hasty_pudding (unregistered) in reply to Chatogaster

    I would say that constants, like most things, should be named for what they represent. Something like ONE_DAY_IN_MILLIS = 1000 * 60 * 60 * 24 is often useful, for example, rather than REGISTRATION_GRACE_PERIOD or something.

    Though honestly I wouldn't even be mad about seeing REGISTRATION_GRACE_PERIOD = ONE_DAY_IN_MILLIS if that was the context useful for someone coming in and reading the code. Which is the only goal worth pursuing anyway.

  • (nodebb) in reply to hasty_pudding

    Though honestly I wouldn't even be mad about seeing REGISTRATION_GRACE_PERIOD = ONE_DAY_IN_MILLIS

    Honestly, that seems like the only same thing to do here.

    If I see

    REGISTRATION_GRACE_PERIOD = 84600
    

    I may understand the meaning, because from context I can guess it. But honestly, I would miss the typo, it should be 86400 instead. And if I'd notice, I still wouldn't know if maybe it is intentional.

    If I see

    DAY_IN_SECONDS = 84600
    REGISTRATION_GRACE_PERIOD = 1 * DAY_IN_SECONDS
    

    then I know it was a mistake. Plus, DAY_IN_SECONDS likely would be defined in a different place than REGISTRATION_GRACE_PERIOD, or at least it would be used multiple times.

    Then again, even that weirdly mixes explicit and implicit units... If there is a global conventions that time-differences are in seconds, than it is fine, but otherwise I'd name it something like

    REGISTRATION_GRACE_PERIOD_SECONDS
    

    Better would be for units to be explicitly expressed through the type system. Date/Time-classes anyone? Though depending on the language it may not be possible to define constant time-spans that way...

  • Craig (unregistered) in reply to PotatoEngineer

    Weirdness with last digits suggests that it might be round-tripping through a double. As I recall, all numbers are double in JS, so it might not even be surprising for that to be the case.

  • banana (unregistered) in reply to OldCoder
    Comment held for moderation.

Leave a comment on “Constantly Finding Magic”

Log In or post as a guest

Replying to comment #:

« Return to Article