Live data from Hacker News

Good Design is Imperfect Design, Part 1: Honest Names

domainlanguage.com

51–60 of 133 posts

Re: Good Design is Imperfect Design, Part 1: Honest Names

#51
post #42

The problem is not the "plus" operator but instead lies in the "month" duration. Not all months last the same number of days, and while we are at it not all days have 24 hours! I'd rather move the explicit (and complicated) choice of what kind of month are you talking about (and thus also the relevant discussion about naming) into the operator that constructs a time interval.

That's not really always possible/practical. It's pretty common to say "in three months from now" in which case defining a month to be 31, 30, 29, or 28 days is not correct. The plain English meaning is to be on the same day of the month, but add 3 to the month value, probably rounding down if necessary. Therefore, 3 months from January 31st 2021 would be April 30th despite going through February which has 28 days.

I think the point of the person you're replying to is to move the ambiguity onto the month object and off the plus operator. So today.plus(1 monthish) rather than today.plusish(1 month).

Re: Good Design is Imperfect Design, Part 1: Honest Names

#52

I disagree with the author on this one. While it isn't a perfect analogue to mathematical addition, neither is floating point math. The bigger issue is that calendar math is tricky and durations cannot always be converted between one another. The correct solution in my opinion would be to have distinct types for this sort of thing to help clear up the ambiguity. Date and time are really tricky concepts to model thoug…

If I may elaborate, the comparison to IEEE floats is apt because they addition is not associative there either:

julia> (1e16 + 1) + 1 1.0e16

julia> 1e16 + (1 + 1) 1.0000000000000002e16

I think the fundamental issue with dates, however, is deeper than "addition is non-associative". It is that "1 month" is a context-sensitive duration (so is a "1 day", due to leap seconds).

I am curious about using intervals. If "{Year} January (no day)" had a representation as "Jan. 1 - Jan. 31", then "Jan. 1 -- Jan. 31" + "1 month" = "{Year} Feb. 1 -- Feb. 28" (or 29 if the {Year} is a leap year".

Re: Good Design is Imperfect Design, Part 1: Honest Names

#53
That there is no ISO 8601 duration in Java has always bugged me. Duration() is just a wrapper around seconds and a millisecond part, so you can’t use it for a calendar duration. Even the concept of an “hour” or “minute” doesn’t work because of leap seconds.

Re: Good Design is Imperfect Design, Part 1: Honest Names

#54
I think it's possible to be both honest and readable.

One way to look at the issue is that the confusion stems from giving the same name to operators of different types, namely the "Instant plus Period" operator and the "Period plus Period" operator.

Period could be implemented as a vector with independent components for days, months, and so on. (I don't know if that's how JodaTime does it, but that's what I would do if I wanted it to have a "plus" operation.) Then it could have a well-defined operator appropriately named "plus", which is both commutative and associative as one would expect.

"Instant plus Period", however, is asymmetric, and cannot satisfy the identities we associate with "plus". So let's give it a name that is also asymmetric. How about "advanceBy"?

2021-01-30.advanceBy(1 month) = 2021-02-28

2021-01-30.advanceBy(1 month).advanceBy(1 month) = 2021-03-28

2021-01-30.advanceBy(1 month plus 1 month) = 2021-03-30

2021-01-30.advanceBy(2 months) = 2021-03-30

That seems much less mysterious to me. Sure, a casual reader wouldn't be immediately confident about what advanceBy returns in all cases, but giving it a name that conveys its asymmetry helps a lot.

Re: Good Design is Imperfect Design, Part 1: Honest Names

#55
post #9

Please don’t have a method named plusIshRoundCeiling() in a library that “might” be used for years in lots of projects :) The plus() one is almost there and you can easily explain the ugly bits in javadocs (with lots of warnings around it so that it sticks out and is addressed hopefully in some next convenient cycle)

I was trying to be funny here! There is lots of room between "plus", which I think is misleading, and the kitchen sink name you quote. Although it depends on how serious the problems were, in this case I'd pick something shorter that still suggested rough edges.

Makes perfect sense, I thought so as well. It just made me think hope somebody doesn't assume this would be the best name in this case :)

Re: Good Design is Imperfect Design, Part 1: Honest Names

#56
post #2

I disagree about "plus" in the JodaTime example. The month addition with corner cases did exactly what I expected because the whole library has been polished to "do what a normal human would do, most of the time". A normal human would not suspect Jan + 1 month, is any month other than Feb. However I suspect, not even reading the documentation, if it were fed 30 or 31 days, rather than '1 month', it would also do exac…

What is 2021-02-28 + 1 month? Is that 2021-03-28 or 2021-03-31? It is far from obvious what a normal human would do most of the time here. The lack of associativity is still a problem. If 2021-02-28 + 1 month = 2021-03-28,then (2021-02-28 + 1 month) + 1 month = 2021-03-28 + 1 month = 2021-04-28. While if I ask what is 2021-02-28 + 2 months (given 2021-02-28 + 1 month = 2021-03-31), most people would say 2021-04-30. W…

The problem is that "What is one month after 2021-02-28?" doesn't have a single meaning in plain human language.

It could mean 30 days in the future. Or the same day of the week 4 weeks in the future (i.e., 28 days in the future). Or the day of the same cardinality in next month. Or any date in the next month. And those are all equally correct.

It's simply not a precise measure of time when spoken from one human to another human in plain language. Indeed, I think we inherently understand it to be an imprecise measure of time just as much as "tomorrow" doesn't mean "exactly 86,400 seconds from this moment". "Next week" doesn't necessarily mean "7 days from now", either. That's why computers don't typically use imprecise terms. They provide feedback and say "this will occur at this time and date".

You always have to check what the operators actually do and what the requirements actually mean when you're working with times and dates.

Re: Good Design is Imperfect Design, Part 1: Honest Names

#58
post #57

Also ``` .plus(1 month) ``` The unknown behavior of 1-30 + 1 month is a red flag that maybe you shouldn't be using "month" as a unit of time because it isn't. Months suck. Bill for services every 10 days or every 25 days or every 50 days instead of every month.

That is a good point. The awkward thing here isn't really "plus" it's "month".

Re: Good Design is Imperfect Design, Part 1: Honest Names

#59
post #57

Also ``` .plus(1 month) ``` The unknown behavior of 1-30 + 1 month is a red flag that maybe you shouldn't be using "month" as a unit of time because it isn't. Months suck. Bill for services every 10 days or every 25 days or every 50 days instead of every month.

But sometimes you need to bill at a certain point in the month. I don't pay my rent every X days, I pay it on the first of the month.

The best solution for that may be something like establishing it as a frequency rather than accumulative addition. But that won't work in every situation. Dates are complex and require lots of thinking to do correctly in some circumstances.

Re: Good Design is Imperfect Design, Part 1: Honest Names

#60
post #17
post #12

Earlier quoted context omitted.

You expected 2021-03-31 + 1 month + 1 month to be different from 2021-03-31 + (1 month + 1 month)? I find this behavior understandable, but not apparent at first glance. Also, FYI, this is not how GNU date works: $ date -d "Jan 28 next month" Sun Feb 28 00:00:00 CST 2021 $ date -d "Jan 29 next month" Mon Mar 1 00:00:00 CST 2021 I could see confusion from this, depending on what libraries you are used to.

The inconsistency with GNU date is more visible from Feb: $ date -d "jan 31 next month" Wed Mar 3 00:00:00 PST 2021 $ date -d "jan 30 next month" Tue Mar 2 00:00:00 PST 2021 $ date -d "jan 1 next month" Mon Feb 1 00:00:00 PST 2021 $ date -d "feb 28 next month" Sun Mar 28 00:00:00 PDT 2021 Edit: This was on my unconscious mind for a bit and I came up with an additional test case to confirm a suspicion I realized. $ da…

I suspected this when I was playing with it, but good to have the confirmation. Thanks!
Post reply on HN