• (nodebb)

    @Remy Ref

    For bonus points, I really enjoy the inconsistent capitalization of PO.

    I suppose we could say these folks have really po' dev processes. Like in technically bankrupt.

  • (nodebb)

    I think the real mistake lies with whoever decided that the components of a version should be numbers separated by a . such that two level version numbers look like floating point numbers - superficially. Other examples of this are

    • telephone numbers (actual a string with a restricted alphabet) being represented as integers
    • currency values (fixed point, or integer number of cents/pence) being represented as floating point
    • social security numbers (see telephone numbers)
    • US zip codes (see telephone numbers)

    I think the phenomenon is widespread enough that it should have a name e.g "faux typing". The phemoneon is characterised by using an inappropriate (probably built in) type because it has some superficiality similarity to the data to be represented.

    Addendum 2024-01-22 08:46: Messed up the bullet points.

  • (author) in reply to jeremypnet

    When I used to teach programming, I would stress: "Only store things as a numeric type if you plan to do arithmetic on them. Do you add phone numbers together? No? Then they're not really numbers."

  • Bob (unregistered) in reply to Remy Porter

    Version numbers should be ints, not strings, because you sometimes do want to do arithmetic on them. Maybe not add version number together, but common operations include incrementing a version number and comparing version numbers. You wouldn't want version "10" to be less than version "2", which is what a string comparison would say.

    A common practice is to have a struct or equivalent holding the major and minor versions as ints, with appropriate comparison functions if needed, although I've also seen the approach of encoding the version as an int, for example as 1000 * major + minor, which is OK as long as you never have more than 1000 minor versions (famous last words, I know...)

  • (nodebb)

    Yeah, you should never use Convert.ToDouble for parsing but double.Parse or double.TryParse. And for any other numeric type you should just directly use the cast operator - so (double)x.

    When it comes to capitalization: Names in .net are either camelCase or Pascal case. So SomeID becomes SomeId or someId, JSONSerializer becomes JsonSerializer or jsonSerializer and NAVCOMAI becomes NavcomAi or navcomAi.

  • Randal L. Schwartz (github)

    Yeah, it's hard to tell sometimes whether version 1.11 or 1.9 is the newer release. Dots-as-separators are deceiving. I imagine commas would be bad in some parts of the world as well.

  • Convert.ToInt32 (unregistered) in reply to Remy Porter

    Someone mentioned that there is a school book for math in the US that wants its readers to add surface temperatures of stars.

  • (nodebb) in reply to Convert.ToInt32

    Subtracting them (to find the difference in the temperature) is far more reasonable than adding two actual temperatures.

  • (nodebb) in reply to Randal L. Schwartz

    Not really. The dot was never a decimal point, it's a delimiter.

    What was misleading were numbers with leading zeros, but luckily these days they are consider bad practice like any other styles that do code painting (see clean code). If you don't use semantic versioning (https://semver.org/) anyway, which is considered good practice these days.

  • (nodebb)

    @MaxiTB ref

    When it comes to capitalization: Names in .net are either camelCase or Pascal case. So SomeID becomes SomeId or someId, JSONSerializer becomes JsonSerializer or jsonSerializer and NAVCOMAI becomes NavcomAi or navcomAi.

    IIRC when it came to representing initialisms, the guidance used to be that two-letter initialisms were left as uppercase, e.g. the System.IO namespace, but for longer initialisms Pascal case was preferred. So System.Xml and System.Net.Http namespaces. Poking at their guidance now I don't see any explicit guidance on how to case standard initialisms.

  • (nodebb) in reply to Randal L. Schwartz

    For version numbers, the individual fields (major, minor, patch) are compared numerically, and the bits after the decimal are not to be considered using the usual logic for the decimal part. Therefore, in your example, 1.11 would be the newer release because numerically 11 is greater than 9.

    See the "Semantic Versioning Specification at semver.org

  • (nodebb) in reply to Convert.ToInt32

    If you're calculating the average temperature, you first need to add all the temperatures.

  • (nodebb)

    Maybe we could get the whole world to switch to a different delimiter. 4@23@572 . Ooops, email parser breaks. 4%23%572 Excel blows a gasket . 4#23#572 Yay! hashtag links go nuts!

  • Officer Johnny Holzkopf (unregistered) in reply to cellocgw

    Do not use numbers. They confuse people and are too science-y. Better use arbitrary code names of imaginary things or misspell something, that's what people are comfortable with. Add expensive-looking words for enhancing. Instead of IniTech Do The Thing version 1.14.3 just use iniTECh DotheThing Shlörtz Magick'ly Glystening Joovel Pro+ Ultra Gold EnterPRIZE edition MaXX secureProtect Expre`s BigAI LeverafluenceUpment - if you name it, they will buy.

  • (nodebb) in reply to WTFGuy

    You are 100% correct. During the old days, there was still no clear best practice in that regard and you have multiple instances of old names in the framework with not following current best practices. Other examples would be the IV instead of Iv for crypto classes or UTF8Encoding class to name a few. Those are still around with .net core, because it would have been a breaking change but other classes where breaking changes happened anywhere were corrected and new classes follow strictly the naming conventions.

    Pretty much a perfect example of follow the best practices not those that broke them before ;-)

  • Stella (unregistered)

    o.O

  • (nodebb)

    Version numbers should be ints, not strings, because you sometimes do want to do arithmetic on them.

    You want to multiply version identifiers by 37? Because that's totally a legal option if they're numbers!

    A saner conceptual representation is to think of a version identifier as a potentially-infinite sequence of natural numbers, but where we conventionally omit writing out all the trailing values if they're zero (joined together with whatever separator you want). You then get a sensible ordering relation on them, but arithmetic is not meaningful. (1.2.3 and 1.2.3.0 are the exact same version ID in this scheme; the former is just the normalized way of writing it down.)

    Unfortunately, some people decide that version numbers need to do nasty things like fitting in a short when done as BCD because they aren't used to thinking ahead... but I'm not bitter about it.

  • Anon55 (unregistered) in reply to Bob

    What do you mean with comparing version numbers? That isn't necessarily defined. Do you really want to tie yourself to that? What if you need to add version 1.1a between 1.1 and 1.2 because a big customer refuses to upgrade to .2 for internal compliance issues, but there is a critical bug?

  • I'm not a robot (unregistered) in reply to The Beast in Black
    For version numbers, the individual fields (major, minor, patch) are compared numerically, and the bits after the decimal are not to be considered using the usual logic for the decimal part.
    No, version numbers are compared according to whatever rules the software author wants, and if they don't specify and it's not obvious, then that's the problem that the previous poster was referring to.
    See the "Semantic Versioning Specification at semver.org
    The creators of that site don't own the concept of version numbers.
  • (nodebb) in reply to I'm not a robot

    If the author says that version 1 is greater than version 2, they're going to get some pointed questions asked of their sanity.

  • markm (unregistered) in reply to dkf

    The problem arises when you compare version 1.9 to version 1.10. If you are using strings, it's going to take a lot of fiddling to make "10" compare as greater than "9". If you are using a structure of two ints, it's easy - unless you're having to work with code written by someone whose math understanding is 4th grade level or worse.

    But if you are using one long integer, e.g., version = 10*majorVersion + minorVersion, there will be a point where code breaks totally. E.g., the user entered "1" and "10" and the system displays "Version 2.0". And there is one way that's even worse - that's to use floating point, so you'll eventually also get rounding errors, so 4.0 comes back as 3.9999999.

  • ismo (unregistered) in reply to Remy Porter

    So money should really be number. As gasoline prices are ( at least here) in sub-cents (Like 1.807€) the floating point ( accuracy problems) or fixed point is valid data type.

  • (nodebb) in reply to Convert.ToInt32

    That was Richard Feynman. He was asked by a textbook publisher to review one of their upcoming titles and unlike all the others he made the mistake of reading it first. A boy is looking at some stars. Stars' temperatures are indicated by their colour [yay! thinks Feynman]: red ones are one temperature, yellow ones are another, green ones [eh? thinks Feynman] a different temperature again ... what was the total temperature of the stars he is looking at? [WTF? thinks Feynman].

  • NextRelease (unregistered) in reply to dkf

    You want to multiply version identifiers by 37? Because that's totally a legal option if they're numbers!

    Following that logic, primary keys should not be numeric either because why would you want to add two identifiers together, let alone multiply them? Still, the increment-by-one operator is heavily used on them. Wanting to do arithmetic on them and wanting to do the full set of existing arithmetic operations on them are two vastly different statements. Similarly, one might easily want to do addition/subtraction and multiplication/division operations on temperatures when you are converting between C and F, and you still wouldn't want to add together the temperatures of two separate liquids when you pour them together.

  • (nodebb)

    So let's try to figure why we have this conversion of revision numbers into a mashed up double... That's because it's the "naive" (and totally flawed) "optimization" to sort them or compare them! The original author probably thought they were being very clever. Simple as that.

    Been there, done that, by the way... Although in my case it was a throw away prototype code and the values were guaranteed to be one digit. Then I implemented a proper VerNum class with a proper Comparable interface implementation and unit tests.

  • TheCPUWizard (unregistered)

    " more reasonable than adding two actual temperatures." -- though indirectly, adding thermal energy values is quite common. However it is only under very, very specific circumstances that one can directly add the temperatures [and these cases, to the best of my knowledge, require the temperatures to be expressed in Kelvin or off-set Celcius]

  • (nodebb) in reply to WTFGuy

    IIRC when it came to representing initialisms, the guidance used to be that two-letter initialisms were left as uppercase, e.g. the System.IO namespace, but for longer initialisms Pascal case was preferred. So System.Xml and System.Net.Http namespaces.

    IMHO, I really feel that they got acronyms wrong. In camel and pascal case, capitalization is at the start of a word (minus the first occurrence for camel) and an acronym expands to multiple words, so it makes more sense to me to have written it like System.XML and System.Net.HTTP or simply instead of XmlParse it feels more natural to write XMLParse as an example, as XML is not a word but letters that expand to one word each. This is what plenty of other languages go by but .Net had to be awkward about it.

  • Isikyus (unregistered)

    Wanting to do arithmetic on them and wanting to do the full set of existing arithmetic operations on them are two vastly different statements.

    Very much agreed.

    I feel like there must be languages that can express this in the type itself (e.g. a PrimaryKey type only defines operations ++, and maybe < and >), though I've never really managed to learn a language that does this.

    Times vs durations are another good example: you shouldn't add two Times, but you can add a Time and a Duration, for instance.

Leave a comment on “Pretty POed”

Log In or post as a guest

Replying to comment #:

« Return to Article