Previous Entry Share Next Entry
Sometimes, I really think programmers shouldn't be allowed to write APIs
device
jducoeur
Now here's a delightful little recipe for bugs:
When creating Date objects, remember that the month parameter in the constructor is zero-based.
So December 1, 2009 is "new Date(2009, 11, 1)". Intuitive, no?

  • 1
What, and the didn't make the day of the month 0 based, too?!

(Deleted comment)
Inconsistent. The month and year should also be zero-based.

Where did you find that little gem?

So, if your an astronomer, the year is zero-based: they'd call 1 BC 0AD.

And besides, as we all know, the very best date functions are 1 January 1970 based.

Perl uses 0-based months, which is very handy when mapping month to an array of month names. Of course it also uses years since 1900 as year, so that's awesome... Day shouldn't be 0-based, because day number is actually the proper name of the day. i.e. the 4th of a month is "4" in a way that "january" isn't "1".

Oh, I understand the reasoning just fine -- I did spend many, many years programming in C. (Nowadays, of course, my gut reaction is that "month" should be a strongly-typed enumeration.)

It's just a *really* great illustration of the tension between the programmer-think zero-based world, and the way most people think about these things most of the time. I mean, even *knowing* this rationale, I would still intuitively expect December to be "12"...

I'm pretty sure it's in Java's standard Date class.

...yes, here it is.

Amusing. That's not where I was quoting from (which was actually Flash), but it's probably the initial origin: Flash almost certainly stole it from Javascript, which probably lifted it from Java. Thus demonstrating that a well-reasoned bad idea *can* live forever...

Actually, I suspect the initial origin was the C library's "struct tm", which was the first place I tripped over the combination of zero-based months and one-based days. Most odd inconsistencies in low-level OS-interface functions in Java are places where the original team just wrapped objects around library functions they were used to. (Filesystem and networking classes in particular come to mind, at least until they added the much better "new I/O" networking stuff a few years ago.)

Flash. I don't think I've ever built a Date object in there by hand before (I'm usually importing them in formats like ms-since-epoch or something like that), but just came across this mention in the Flex Charting documentation...

Jeezuz. Even I would know better.

Well, that's *because* you're not a programmer. In the programming world, everything starts with zero, often whether that makes semantic sense or not. (Largely because of the way arrays work, as Dave mentions upthread -- the logic tends to permeate programmer-think...)

Oh, yeah, I get that, and actually I've been familiar with the starting-with-zero thing since I learned BASIC in 1970. All I can answer is "what cellio said", below....

Really? When I learned BASIC in about 1979, arrays were 1-based.

My second language was Lisp, in which one doesn't usually have to worry about positions in arrays, because one usually iterates over list elements directly without mentioning their positions.

My third language was Fortran... 1-based arrays.

My fourth language was SPL, which I think had 0-based arrays... but I didn't really get anything working in SPL, so I'm not sure that counts.

When I started college, we used Pascal, in which arrays started wherever you pleased: want an array indexed from 27 to 49, or from -6 to 2? Sure, no problem!

Later in college, I used PL/I, which also used 1-based arrays, IIRC. The first language I encountered that insisted on 0-based arrays was C, in my last year of college.

Which version of BASIC? In 1979, the explosion of home computers meant that BASIC was a maze of twisty versions, all different. All the ones I ever used had 0-based arrays, but I think I did hear about one with 1-based. The PET, maybe?

My first BASIC was on an HP/2000 minicomputer. Then my school got a roomful of Atari microcomputers, on which I think arrays were 1-based.

Yeah, that does sound right.

I had a TRS-80 Color Computer, and later a Franklin (an Apple II clone); most of my friends had Vics or C64s. The language barrier could be fairly high—I remember one time I was writing a program, and for some reason people were watching, and the Commodore users didn't know what ELSE was.

Hmm. Well, if you're asking for documentation, I have no idea what version it was, but I know I've known about the starting-at-zero business from my introduction to the idea of a computer, and this was it. My team needed to use "the computer" for a lab project and my professor tossed me *THE* manual and said "you have two weeks".


I learned BASIC for a Behavioral Pharmacology Lab course which consisted primarily of physically building the lab -- I'm not kidding. There were two things called "computers" at the Mass. College of Pharmacy in those days. One was really a teletype terminal, apparently connected to a Forbin-Project style behemoth at Bethesda; it had no monitor, just a printer with a continuous roll of yellow paper. The other was a Lovecraftian array of boards on a rack, with names like "J-K Multivibrator". Anyway, I needed to use The Computers for our project once the damn lab, and our Skinner Boxes, got built. By us....

In case you're wondering, the experiment involved stopping the metabolism of mescaline at a couple of points, in rats, and observing their behavior. Results (completed by the next class after I graduated) were inconclusive. I didn't learn a whole lot of behavioral pharmacology from that lab, but I did actually learn a little BASIC.

Oy!

I understand that zero-based is the norm. Really I do. But for things where a numerical representation is already in common use, for heaven's sake don't mess that up! And doubly so if they're being inconsistent and not treating the day the same way. Sheesh.

Programmers will create APIs, but more companies need to treat that as a proposal to be reviewed and perhaps revised by people who can think more like users.


I'd like at some time to tell you about some of the pharmacy software packages I've used at work (including the current one, which is inexplicably the most popular). SOOO not written by pharmacists...and in ways you may find amusing in a "headdesk" sort of way %^).

And why? Well, arrays (in C, C++, Java, and related languages) are 0-based. Why does that matter? Well, the Date class might need an array of month names and/or month lengths. So what?

At this point there are three choices for designing the Date class.
1) You can present an API in which month numbers are 1-based, but use 0-based internally. A bit of an annoyance, and it costs an addition at every constructor or getter call, but nothing that a first-year programming student shouldn't be able to handle.
2) You can present an API in which month numbers are 0-based, and condemn your users to an eternity of dealing with bugs that you could have prevented once and for all. Or...
3) You can present an API in which month numbers are 1-based, and actually store them 1-based internally, with dummy 0-th entries for the monthName and monthLength arrays. At the cost of a pointer and an integer of unused memory, you've avoided BOTH the run-time cost AND the bugs.

(Realistically, those arrays shouldn't be in the Date class anyway; they should be in localization objects, so the memory cost is a pointer and an integer per localization object. How many programs have more than one or two of those?)

Even better, of course, would be to use a language that (like Pascal) allows you to index an array in whatever way is natural for the problem. Adjusting array indexes shouldn't be a programmer's problem, and it shouldn't carry either a run-time cost or a memory cost; it's a classic job for a compiler.

Adjusting array indexes shouldn't be a programmer's problem, and it shouldn't carry either a run-time cost or a memory cost; it's a classic job for a compiler.

Assuming the array bounds are fixed at compile time, that is. The size of arrays in Java is a runtime property; if there were a base offset, I expect it would be, too.


If Java supported different array indexing bases, it might indeed be cleaner and more elegant for this to be a run-time property. But it wouldn't carry any significant run-time cost, because the Java run-time library has to check array indices against 0 and length already. The offset calculations wouldn't be any more difficult, since the run-time representation of the array could include the address of its 0-th element (whether or not there is a 0-th element). This would need to be recalculated every time the indexing base is changed, but something analogous already needs to be done every time the size is changed now.

But it wouldn't carry any significant run-time cost, because the Java run-time library has to check array indices against 0 and length already.

Ah, right, good point.

the run-time representation of the array could include the address of its 0-th element (whether or not there is a 0-th element).

Clever.

something analogous already needs to be done every time the size is changed now.

I don't think Java arrays can be resized; but that just means nobody would be surprised if the base couldn't change, either?


I don't think Java arrays can be resized

True, but other than this, all the same reasoning applies to ArrayList, which can be resized.

but that just means nobody would be surprised if the base couldn't change, either?

Makes sense to me.


I often find myself in need of an 'unspecified' value, thus
Month[0] = "Unspecified"
Month[1] = "January"
etc.

Solves all your current problems plus some future ones too.

  • 1
?

Log in

No account? Create an account