Long-term review: Apple Aluminum Keyboards

I mentioned Apple's aluminum keyboards earlier, but having recently bought a couple more, I thought that was a fact worthy of mention. The one I had grew on me and my fingers grew lazy enough that I started to get annoyed at having to lift my fingers so high to clear the tops of the front rows of keys on my work keyboard, or the "spare" keyboard I use with the MacBook Pro if I'm planning on doing some work from home.

The day I replaced my work keyboard, someone came into the office talking about cleaning keyboards, prompting me to said that the best feature of Apple's aluminum keyboards is that (so far) they appear impossible to get dirty. They begged to differ and suggested that the keyboard's best feature is that it looks amazing.

He had a point. I probably wouldn't have bought my first one if they didn't look so damn cool.

So, after a few months of use, the aluminum keyboard's feel grew on you to where other keyboards , and the beauty of its appearance doesn't wear off.

Having two (different) keys labeled "delete", one of which is actually backspace, continues to be retarded, and the numeric keypad continues to be useless to me.

(Speaking of which, the only other keyboard-related development I have to report is Microsoft's SideWinder X6 "gaming keyboard". It's not without a numeric keypad, but it does let you detach the numeric keypad to switch sides, and it's not obvious that you have to reattach it. Unfortunately, although the "editing pad" is fine, the esc key is in the wrong place, there's an extra row and extra column of useless keys, and two enormous dials. Plus the thing's almost as deep as it is wide, very clunky-looking, and may or may not require special Windows-only drivers. Microsoft usually says their keyboards and mice work with Mac OS, but they don't with this one. That may just mean that various features you don't actually want won't work, but who knows? And if they're not interested in telling me, I'm not interested in buying one to find out.)


CACM: no longer sucking

Communications of the ACM used to be great. When I went to university, I spent nights reading back-issues, and can honestly claim to have read every single issue. In the early days, even the letter pages were great: people were arguing about how to correctly implement semaphores and whether gotos were harmful. And in the main body of the magazine, others would be showing off their new "quick sort" algorithm, introducing a new time-sharing system called "Unix" or a new distributed packet switching system called, of all things, "Ethernet".

And then, somewhere in the 1990s, it turned to shit. All management and business and "IT" and government projects and sociology and just random, well, shit. So although I became a member of the ACM when I left university (mainly so I could get the SIGPLAN proceedings without finding a university library, and so I could avoid being one of those creepy old obviously-not-a-student guys who hangs around university libraries), for most of the past decade, I've "read" CACM in the distance between my letter box and the kitchen bin.

I still read the SIGPLAN conference proceedings, though, because I'm interested in that stuff, it's peer-reviewed (so even when it's crap, it's at least coherent crap written by people with CS degrees), and it gives me an idea of what research is being done in that sub-sub-sub-field.

CACM, though, wasn't even fit to wipe your arse on. (Glossy paper, you see.)

The past few issues, though, have picked up substantially. I didn't comment on the first one, because even a gobshite like Adam Sandler or Will Ferrell might make a good film once in their lives. But we're on the fourth non-shite issue of CACM in four months, and that's better than they managed throughout the entire 1990s. Hell, you'd have to go back to the 1970s for that kind of quality.

Sure, it's not perfect, but it's a huge leap forward. The "news" is now reminiscent of New Scientist, rather than just being a random collection of six-month-old Slashdot stories. The random articles have managed to be mostly decent overviews of mostly sufficiently technical stuff. And the "research highlights" section, well, that's the lesson they learned from Nature/Science, and it's done beautifully. They get someone who knows the subject write a one-page layman's introduction to a paper, followed by the actual paper, that you probably won't fully understand unless it's a field you know. So last month had Mark Moir (senior staff engineer at Sun) introduce/review a paper on using transactional memory in operating systems, followed by the paper; then Hagit Attiya (professor of CS at the Technion) introducing a distributed algorithm for computing the k-th smallest element, followed by the paper.

Other recent-issue articles have included Adam Leventhal's "Flash Storage Memory" on using flash as another level in the storage hierarchy (rather than a straight disk "replacement"), Mark Oskin's "The Revolution Inside the Box", reviewing the last decade of computer architecture research (not all multi-core, but, yeah, plenty of that). Plenty of papers on transactional memory (which it's been pretty hard to avoid lately anyway, but it's nice to have someone picking out just the good bits). And if human interest stories are more your thing, there's been the heartwarming two-part serial about Don Knuth and his massive organ.

This, the new CACM, is a thing of beauty. This is something you'd actually pay money for. (Which is nice, because I've been paying money for it for just over a decade now.)

What's not good? Well, there's some sloppiness; multiple (different) expansions of the acronym XML in the same issue, for example. (And seriously, if it's as mainstream as XML, does expanding the acronym help anyone? If they didn't already know what it meant, the expansion isn't going to clue them in. Typing "XML" into their favorite search engine will, and if they're incapable of doing that themselves, they're a lost cause.) Not all of the articles are of a high-enough quality, with hints of the bad old 1990s "business wank" CACM. There was some article last month from Michael Cusumano (a professor at the MIT Sloan School of Management) that was both irrelevant and factually incorrect; I gave up before coming to his point, assuming he had one.

Back on the bright side, the 2008-10 issue contains the paper "Scene Completion Using Millions of Photographs" by Hays and Efros that's exactly what I want: something interesting, accessible, and well outside my usual sphere; something I wouldn't have come across on my own.

Hopefully the future contains more of the new stuff and ever less of the old stuff.

If you're serious about CS, and interested in having some vague idea of what kinds of things people are looking at in our increasingly wide and diverse field, I can actually recommend CACM for the first time since the 1970s. I finish an issue feeling like I've learned something, rather than feeling like I'm an idiot for paying for some sociologist or MBA to gibber on about stuff that's not true, not falsifiable, or not pertinent.

The only downside to CACM being worth reading again is that it's yet another demand on my copious free time.


Review: "Effective Java", 2nd edition

One of the benefits of working at Google that I hadn't heard about until I joined is that you're both actively plied with books when you start, and given annual credit to buy books of your choice (without the hassle of filing expenses).

Any developer who wanted a copy of the second edition of "Effective Java" was offered one when it came out, and I eventually read through it, and I finally found the time to write down a few notes...

The first thing you'll notice is that the second edition is much thicker than the first edition. The last page of actual content in the first edition was page 232; it's page 315 in the second edition. That might not seem like much of an increase, and there's a way to go before it hits the "weighty tome" territory of something like "Mac OS X Internals", but for me those extra pages take "Effective Java" over the threshold from "slim volume" to "book".

In the years from 2001 to 2008, the Java language has changed a lot. Already by page 16 (item 2), we're faced with a bounded wildcard type. Those of us who've been using Java between the two editions have also changed a lot, and a lot of the advice from the first edition, even if you weren't already following it at the time the book came out, has since become the standard idiom that everyone above a basic level of competence uses. As a result, the second edition feels very repetitive.

I really wish there were two variants: "diffs" for those of us who know the first edition and have been following its advice for years, and "from scratch" for those new to Java (or who don't read much). It's not hard to imagine "Effective Java" making a better website than a book, too. Most of the items, especially if you're familiar with the first edition, are things you can grok from the title, with little to add for the expert.

This is in stark contrast to how I remember the first edition. I remember being persuaded of several idioms by the first edition. Some things like "Return zero-length arrays, not nulls" were things we'd already worked out for ourselves, and "Minimize the scope of local variables" has been something that good programmers have understood since the beginning of time, but I remember it feeling really good to hear a voice of authority say "Avoid unnecessary use of checked exceptions". We all knew there was something wrong, but you had to have a certain stature to stand up and say "the emperor has no clothes", and the guy who was the public face of the collections classes had that stature.

The interesting thing reading the second edition is that it's likely to elicit a raised eyebrow now and again, and remind you that, presumably, there are (new) beginners who need to be told of things we've all been doing since the 1990s.

As an aside, an interesting difference between "Effective Java" and "Effective C++" is that my reaction to the latter was to come up with a set of SOPs that mainly boil down to "don't use C++ feature x". Whereas "Effective Java" was more like "use idiom x when using Java feature y". An interesting consequence of which is that I'm much better able to articulate why I do things the way I do in Java than I am in C++.

Anyway, what stood out for me in the second edition of "Effective Java"?

I didn't know about @code and @literal in JavaDoc; I tend to just write as if comments are plain text, since my API documentation isn't likely to be published anyway, and is more useful to me and others if it's readable in the source form, in contrast to Bloch's "generated documentation readability trumps source code readability". When you're the public face of the collections classes, I guess you have a different perspective.

Bloch's claim that AbstractList.removeRange is "of no interest to end users of a List implementation" made me laugh. And not in a good way. I think that specific API design error has singlehandedly caused more O(n^2) behavior in code I've been exposed to than any other, as people fail to find a bulk remove and use a "for" loop instead. Even if you do know about subList().clear(), it's hard to consider that anything but ungainly. Bulk operations seem more fundamental to me than the idea of a view, I guess, and I rarely have use for views other than because I'm trying to removeRange. Personally, I think that was an attempt to introduce an non-Java idiom into Java, and it didn't really work.

Perhaps because of Bloch's background, much of the advice in the book seems overly biased towards public API. This is understandable, but even if one takes the position that all API should be designed as if it were library API, I think it's hard to argue that you should make any more public API than absolutely necessary. YAGNI, after all, and anyone who hasn't realized that it's far easier to add stuff than to take stuff out or fix stuff, well, that person's obviously not a golfer.

Another interesting contrast with C++ is that, whenever you read a book on C++ you're likely to spend most of your time thinking about how the language could be improved, but reading books like this on Java, you're more likely to think about how the libraries could be improved. It's particularly amusing that the "Effective C++" item "Make interfaces easy to use correctly and hard to use incorrectly" (advice valid for any language, and that ties in to my earlier concern about exposing too much API) has an example "pathologically bad" Date class that's not actually as bad as the real java.util.Date.

I've seen Stroustrup actually use the real Java Date and Calendar classes as examples of bad design on a slide, and I felt it was a shame he detracted from his own point by implying that it was Java's fault. As if you can't write utter crap in any language. As if even good programmers don't have days where everything they touch turns to shite.

As if bad design (like good design) isn't universal.

Java programmers have the advantage of a large and readable library. So there's no excuse for not having seen a large amount of code, much of it high-quality, but enough of it low-quality, or old enough to be using idioms that we've since learned don't work out well. So for an experienced Java programmer, "Effective Java" is a quick read, many chapters of which could be replaced with "use common sense" or "copy the good examples, ignore the bad ones". It's sad to see the number of "obvious" points from the first edition that the JDK still falls down on. "Adhere to generally accepted naming conventions" is one that's getting worse with time as more new JDK APIs arrive using the less popular naming conventions and making them more generally accepted (using "X" and "setX" instead of "getX" and "setX", say, which isn't bad in and of itself, but is just one little bit of extra trivia we have to keep around that adds no value, and is too late to retrofit to the entire JDK). "Include failure-capture information in detail messages" is my personal unfavorite, though it's something programmers in all languages get wrong. Why aren't we teaching "how to write a good bug report" and "how to write a good error message" in the schools? Can you really be a productive member of society without these skills?

The synchronization stuff's been usefully updated in the second edition, and is a lot clearer now. It's a shame that stuff like that, which I'd go so far as saying a majority of Java programmers don't properly understand, isn't visibly treated as being any more important than all the fluff about exceptions and serialization and doc comments and (I'm not joking) the performance of string concatenation.

CopyOnWriteArrayList and its suitability for listener lists was new to me (despite dating back to Java 5). I'll have to remember that. It would be nice to have a new Java tutorial, for experienced programmers, that shows the current best idioms, and explains the rationale. Listener lists are a lot harder to get right than you might hope.

Item 69 settled an argument we'd been having at work. Should you call ConcurrentHashMap.get before calling ConcurrentHashMap.putIfAbsent? Our argument was focused on how expensive the constructor for the to-be-inserted object is. The documentation led us to believe that the implementation effectively does a get straight away, which is true, but the documentation is missing the rather important fact that a lock is taken out for the duration of the call to putIfAbsent. When Bloch presents the get-then-putIfAbsent idiom, he gives this as the motivation, and checking the source shows he's right. I've filed Sun bug 6737830 for improvements to the documentation. The evaluation for that bug is interesting, as it argues back in the opposite direction.

It's nice to see CountDownLatch advertised. That's my favorite low-level primitive.

Bloch suggests using System.nanoTime in preference to System.currentTimeMillis for interval timing, because it's more accurate, more precise, and unaffected by system clock changes. I'd been using System.nanoTime in new code, but given that last advantage maybe it's time (ho ho) for a more thorough toilet-cleaning.

The book ends with a bunch of items on serialization, which was rather surprising to me. I haven't written a (deliberately, explicitly) serializable class in the last eight years. I don't know if that's because serialization isn't a mainstream thing, or because it was eight years ago that I last wrote Java (rather than C++) for a living. Maybe just behind some narrow door in all my favorite bars, Java programmers in red Pendleton shirts are getting incredible kicks from squirting serialized objects at each other. Who knows?

Every time I've touched Java serialization I've come away with the feeling that it's sufficiently broken in a sufficient number of ways that I'm better off just avoiding it. Gangrenous appendages eventually fall off of their own accord, don't they?

If you're a Java programmer, you ought to read this book. It's not going to be a life-changing experience for many. (If you find it is, you probably need to ask the best programmer you know to help mentor you.) This isn't as important a book for Java programmers as "Effective C++" is for C++ programmers. It's also not as important a book for Java programmers as are Goetz's or Wadler's recent books.

But you can't not have read it. Get work to buy a copy and hand it round as each of you finishes. You can read through it in a day, and quicker than that if you're familiar with the first edition and you've been writing (and reading) Java in the intervening years.