News for hackers. Stuff that matters.
Re:C++ Is the Next C++ by kllrnohj on Wednesday November 02, 2022 @07:49PM (#33444546)
> Is "Month" a 1-based month ordinal? A 0-based month index?

Unlike with an bare int, a "Month" type has places to actually document all that. So your counter argument, which is entirely the same for an int anyway, is utterly absurd.

> This works until some jerk buries it in #ifdef soup and causes your IDE to lie.

I don't really know what your point even is here. Your ide or code base is bad, therefore everyone should share your pain?

If your ide can't resolve it then go look up the docs the old fashioned way. It's the same end result of a wrapper type being vastly superior to a bare int. I can make a comment in a header or a man page or whatever for a "Month" type to answer all your questions. I could never do the same for an "int" variable.

It really sounds like you're just wanting to obsessively nitpick the specific example of "Month" than anything about what the guideline is even saying. If you're just too lazy to make a Month then sure knock yourself out. But at least be honest that you're just being lazy in the now with a hope it doesn't bite you later, don't pretend you're making an actually better or more readable decision. We all take the lazy out from time to time.

Re:C++ Is the Next C++ by MaulingMonkey on Thursday November 03, 2022 @03:21AM (#33448017)
> Unlike with an bare int, a "Month" type has places to actually document all that

Good chance it won't actually be documented there though, or that the documentation will lie. Similarly, that documentation can easily live on a date-style object, where it's more likely to be accurate.

> So your counter argument, which is entirely the same for an int anyway, is utterly absurd.

No, I've eliminated several possibilities with a plain int that you've conveniently left unquoted. I do still have some ambiguity, but less, and gained clarity in several things you've - again - conveniently left unquoted. It's not perfect, but it's an improvement.

> I don't really know what your point even is here. Your ide or code base is bad, therefore everyone should share your pain?

Every codebase has some bad code, and my point is - even with good IDE assistence - a typedef still requires digging. And if my own personal experience is anything to go by, most codebases have a lot of bad code.

If you've been blessed with only perfect codebases handed down to you from the gods themselves, pristine and pure, maybe Month is less opaque for you than it is to me. You have my sympathy for the shock and horror you'll experience should you ever touch code writtten by mere mortals ;)

> It's the same end result of a wrapper type being vastly superior to a bare int.

I challenge you to share a single real life bug that you've managed to catch or prevent with a strong month type. Go on, I'll wait. Or show me some code from a real codebase where a stronger month type actually improves readability more than, say, a variable named month_index or month_no. Show me a concrete example of this vast superiority improving the readability of a function in a real codebase. Or where it's lack has made things confusing, and the mere addition of "Month" would provide clarity.

> I could never do the same for an "int" variable.

You can absolutely attach comments and documentation to variables, methods, and properties.

https://learn.microsoft.com/en-us/dotnet/api/system.datetime...

Oh gee, is that an `int` month property that states it's range? Yes. Yes it is. And I don't have to drill further into the documentation to look at the type of the property, and can just look at the property? Bonus points!

> It really sounds like you're just wanting to obsessively nitpick the specific example of "Month" than anything about what the guideline is even saying.

I'm providing context to point out the limits of the guideline and where it goes too far, using it's own example. Hardly obsessive nitpicking.

> If you're just too lazy to make a Month then sure knock yourself out. But at least be honest that you're just being lazy in the now with a hope it doesn't bite you later, don't pretend you're making an actually better or more readable decision. We all take the lazy out from time to time.

Don't get me wrong, I'm incredibly lazy. Otherwise known as cost efficient. I have better things to do than to create or untangle a mess of opaque types that do little more than obfuscate the code for some hypothetical type safety that - based on personal experience - won't actually add any safety in practice, won't catch any bugs, won't provide a meaningful improvement to documentation or code readability, and will just slow me down and take time away from working on something that might actually be important (perhaps some practical type safety.)

I would hope my coworkers also have better things to do with their time as well. The possibilities and backlog are infinite, but our time is not.

Re:C++ Is the Next C++ by account42 on Thursday November 03, 2022 @05:48AM (#33448902)
> Good chance it won't actually be documented there though, or that the documentation will lie

The most natural fit for the Month type here is an enum, enum class or something that wraps one with additional functionality. And while sure you could have enum Month { }; and then use Month(0) for january or whatever, that's just deliberate obfuscation and not what anyone reasonable would do for normal code. And it's still not worse than an int.

> No, I've eliminated several possibilities with a plain int that you've conveniently left unquoted.

Do you? Someone could have added a #define int float after all. Your arguments that just because someone could obfuscate the type in some way that that inherently makes using a Month type bad is just that: absurd.

> Oh gee, is that an `int` month property that states it's range? Yes. Yes it is. And I don't have to drill further into the documentation to look at the type of the property, and can just look at the property? Bonus points!

Except if you are assingning one month property from another month property you have to check the documentation for both that they math (and not just almost match). Whereas with a strong type the compiler checks that for you.

Re:C++ Is the Next C++ by MaulingMonkey on Thursday November 03, 2022 @10:18AM (#33451387)
> The most natural fit for the Month type here is an enum, enum class or something that wraps one with additional functionality.

And I remain unconvinced that any of those "natural fits" add value.

> Do you?

Yes.

> Someone could have added a #define int float after all.

That would be straight up undefined behavior. Can't redefine keywords. Even a badly defined "i32" is clearly buggy enough that even the most foolish coworkers won't do it, and cleaning up after the outright malicious is at least more straightforward.

You're trying to say that the likelyhood of stupid tech debt from weird backwards compatability nonsense, and straight up intentional chaos, but I don't buy that you even believe it yourself. I have seen plenty of the former in real codebases, and a tiny fraction of the latter. Even the broken-ass codebases that I've worked on that have invoked undefined behavior by redefining keywords haven't gone as dumb as #define int float.

I've seen #define true 1 though.

> Except if you are assingning one month property from another month property you have to check the documentation for both that they math (and not just almost match). Whereas with a strong type the compiler checks that for you.

Even if you have two type-matched "Month" properties, if they belong to dates in different timezones, there's a good chance you've just written a bug by forgetting to account for the difference - and that's a far more likely bug to slip through the cracks than mixing up month index and month ordinal. And when you don't have type-matched "Month" properties, the author will likely write the same code they would've with integers, just with a bunch more casts, if only because they don't want to eat the recompiles of touching a date/time header that gets included goodness knows how far and wide.

Putting it another way: I'd argue that the manipulation of individual months is already inherently not type safe, as it lacks enough context to be type safe.

Re:C++ Is the Next C++ by kllrnohj on Thursday November 03, 2022 @09:42AM (#33450817)
> You can absolutely attach comments and documentation to variables, methods, and properties.

So instead of documenting it in a single place, your argument is to document it in dozens or hundreds of places and somehow that'll never get out of date. Even though the single documentation in a single place must be assumed out of date?

Cool story bro.

> Oh gee, is that an `int` month property that states it's range? Yes. Yes it is. And I don't have to drill further into the documentation to look at the type of the property, and can just look at the property?

How do you know what is January? Is it 0? 1? Or something else entirely because someone thought it'd be cute to use the value of "JAN" since, after all, that 4 byte string perfectly fits in a 4 byte int.

> I have better things to do than to create or untangle a mess of opaque types that do little more than obfuscate the code

    enum class Month : int {
        January,
        February,
        ...
    }
Holy shit look at that obscene effort and obscurity! I should enter IOCC with that unreadable masterpiece.

> won't actually add any safety in practice

    `new Date(5, 10, 2020)`
Quick, what's the order of those arguments? Is it day month year? Or month day year like Americans like to do?
Re:C++ Is the Next C++ by MaulingMonkey on Thursday November 03, 2022 @10:53AM (#33451931)
> So instead of documenting it in a single place, your argument is to document it in dozens or hundreds of places and somehow that'll never get out of date. Even though the single documentation in a single place must be assumed out of date?

When the documentation lives alongside the actual concrete use cases, it at least tends to get fixed when those individual concrete use cases are changed.

> How do you know what is January? Is it 0? 1? Or something else entirely because someone thought it'd be cute to use the value of "JAN" since, after all, that 4 byte string perfectly fits in a 4 byte int.

You didn't read the documentation I linked I see. "The month component, expressed as a value between 1 and 12." - this rules out fourcc nonsense, this rules out 0, this leaves only 1.

> Holy shit look at that obscene effort and obscurity!

0-based? Nice curveball number #1. Someone will probably refactor it to make it 1-based later, so that's nice curveball number #2 that will break all to/from int casts for interop. Or fix them - lets be honest, someone's going to cast (Month)some_var_that_is_1 for interop and expect January, and then probably cast back to (int)month for more interop, resuling in bugs canceling out bugs. I've also seen similar enums get accidentally reordered by someone fat-fingering Alt when pressing up-arrow, swapping lines, changing the values, for curveball #3... hope it gets caught in code review! It won't if such a typo sneaks into the initial version, but one can dream! So now I gotta read more than you could bother to type out...

> Quick, what's the order of those arguments?

Year month day. Easily verified by intellisense, too, since we're clearly okay with that in-thread. Your code will throw ArgumentOutOfRangeException. Someone will add these kinds of overloads for "convenience" even if you have a Month enum too BTW, so don't pretend that it's existence fixes things. I can totally get behind named arguments:

    new Date(year: 2020, month: 10, day: 5)
Or "named" constructors:

    Date.FromYearMonthDay(2020, 10, 5)
Either of which I'd prefer over:

    new Date(new Year(2020), Month.October, new Day(5))
Programmer style YYYYMMDD isn't that bad either, honestly. But, even with that last one: What the heck is the timezone? UTC? Local timezone of the executing machine? Timezone of whatever machine is interpreting the Date instance? I'm gonna have to read the docs regardless...
Re:C++ Is the Next C++ by kllrnohj on Thursday November 03, 2022 @12:03PM (#33453114)
> 0-based? Nice curveball number #1. Someone will probably refactor it to make it 1-based later, so that's nice curveball number #2 that will break all to/from int casts for interop. Or fix them - lets be honest, someone's going to cast (Month)some_var_that_is_1 for interop and expect January, and then probably cast back to (int)month for more interop, resuling in bugs canceling out bugs. I've also seen similar enums get accidentally reordered by someone fat-fingering Alt when pressing up-arrow, swapping lines, changing the values, for curveball #3... hope it gets caught in code review! It won't if such a typo sneaks into the initial version, but one can dream! So now I gotta read more than you could bother to type out...

This whole made up scenario equally applies to ints but even worse. At least with the type I can find the usages. The Month type is at worst not better than the int type, but it's never worse which is the important part of being a guideline.

Your argument is basically boiling down to "the safer code is more error prone because I'll just suddenly be a way worse programmer for some reason whereas I can totally nail the dangerous code without any possibility of mistakes ever because... uh... just trust me or something"

> Year month day.

Says who? Remember documentation doesn't exist in your hypothetical argument world, which is why a type is somehow bad or something.

> Easily verified by intellisense, too

This is what intellisense will show me: `Date::Date(int, int, int)` That's not verifying fuck all. If we were using opaque types then intellisense would verify it for me.

> I can totally get behind named arguments:

Sure, is that your guideline? We don't need opaque types because we only ever used named arguments and return values don't exist?