Guava

A public service announcement for Java programmers.

Google has released as Free software a bunch of convenience libraries used internally in Google Java code. The project is (very cleverly) called Guava.

The libraries span a huge range of functionality, but I think that in general they help to promote a more functional programming style and they paper over some of Java's warts.

Here are three of my favorite things from Guava, but if you read the Javadocs you will undoubtedly find more cool stuff. Looking at all of this, you might decide that it's all simple stuff that you could implement yourself in about five minutes. Of course you could (in some cases, anyway), but why would you?

Immutable collections

Create an immutable list (as you might recall, every Java array is mutable, which can be a huge source of pain):

List<String> answers = ImmutableList.of("yes", "no", "maybe");

There's also a Builder pattern for more complex constructions, and analogous classes Immutable{Map,Multimap,Set,SortedMap,SortedSet}.

Collection factory methods

Here's some standard Java code to instantiate a collection:

List<Foo> foos = new ArrayList<Foo>()

Using the Lists class, you can rewrite that as the following:

List<Foo> foos = Lists.newArrayList()

Usually factory methods are a way for you to give the callee the flexibility of returning different classes at runtime. That's not the case here— Lists.newArrayList will always return an ArrayList (unsurprisingly). But Java does type inference for a call of this type, so you save the hassle of having to repeat yourself by writing the generic type Foo on both sides of the assignment, every time you create a new collection.

There are analogous classes Maps and Sets, which also contain other useful utilities in addition to these factory methods.

Splitter

Some simple illustrative examples for splitting a string using Guava's Splitter class:

Splitter.on(",").split("foo,bar,baz");
// ==> an iterable containing "foo", "bar", "baz"

Splitter.on(",")
    .trimResults()
    .omitEmptyStrings()
    .split("foo,bar , baz,,,");
// ==> an iterable containing "foo", "bar", "baz"

But wait, doesn't Java already do string splitting? Yes! Yes, it does. And this is how (emphasis mine):

String.split

public String[] split(String regex, int limit)

Splits this string around matches of the given regular expression.

The array returned by this method contains each substring of this string that is terminated by another substring that matches the given expression or is terminated by the end of the string. The substrings in the array are in the order in which they occur in this string. If the expression does not match any part of the input then the resulting array has just one element, namely this string.

The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. If the limit n is greater than zero then the pattern will be applied at most n - 1 times, the array's length will be no greater than n, and the array's last entry will contain all input beyond the last matched delimiter. If n is non-positive then the pattern will be applied as many times as possible and the array can have any length. If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded.

This is a bizarre and unmemorable edge case in the API. I guarantee that upon finishing this paragraph, you will promptly forget about it until about two hours into debugging a failure caused by it. You can save yourself some grief if you just use Splitter. Stay away from String.split.

Thinkpad TrackPoint Scrolling in Ubuntu Maverick/10.10

Update: these steps seem to work on Ubuntu Natty/11.04 for me, as well.

My fellow citizens, our long national nightmare of having to use bad pointing devices is over.

Starting with Ubuntu Maverick/10.10, configuring scrolling with the middle button and the TrackPoint is now really easy:

  • Install gpointing-device-settings (sudo aptitude install gpointing-device-settings)
  • Run gpointing-device-settings &, enable the Use wheel emulation using button 2, and enable both vertical and horizontal scrolling.

(gpointing-device-settings is not new but Maverick is the first time it has really worked well for me.)

Update: some people are reporting that g-d-s settings are lost after suspend. If you run into this, you might try these alternative instructions.

Designing for colorblindness

Public service announcement: some 8% of men have some form of colorblindness.

A couple of people have pointed me to this nice article on colorblind-friendly design, by Masataka Okabe and Kei Ito. Useful reading for anyone who designs for print, presentations, or UIs.

It's a good overview of the underlying theory/physiology of colorblindness and gives many tips for conveying information through channels other than color.

The authors also provide this handy colorblind-friendly color palette:

Backups and rdiff-backup

I always thought nearlyfreespeech.net's advice on backups was good advice:

You should adopt a backup policy that assumes we are storing crates of sweaty dynamite on top of the servers that hold your important data. (Even though we aren't.) [NFSN FAQs]

If you only have one copy of something, stop what you are doing, obtain a disk, and replicate it.

Here are some brief notes on my backup setup, including some things I've learned since I last wrote about backups. (I had a disk failure last December and restored everything from backup. No tears, no sweat. In fact the exact same thing seems to happen about once every year, which I suppose is a good testimonial. I'm probably due for a disk failure real soon now.)

  • My first line of defense is backing up to a secondary HDD in my machine. I mostly use rdiff-backup now (and only rsync for huge files, like disk images). This system seems to work well. rdiff-backup creates reverse diffs on each backup so you can retrieve old versions. All the diffs go in the rdiff-backup-data subdir; if you remove that you just get a plain mirror, like what rsync would do.
  • I wrote a FUSE filesystem, rdiff-snapshot-fs, that displays rdiff's repository format as a series of mirrors in order to make it easier to browse historical snapshots. Doing a restore of individual files from time to time is key to ensuring your system is working when you really need it.
  • Rather than scheduling backups with cron and having to leave my computer on at night or, alternatively, having backups happen while I'm working, I bound a hotkey to a script that backs up and then puts the computer into suspend. I run it when I leave the computer for the day, every day.
  • I also rsync to other backup backup locations, including a portable HDD that stays in a safe place when I'm not using it.
  • When restoring from a mirror, the -c flag to rsync is useful. It makes rsync compare the checksum of the data being copied back with the checksum of the original. Then if you have multiple backups of the same stuff you can easily identify and reconcile any differences between them.
  • I did try rsnapshot. Unfortunately it caused my system load average to shoot through the roof, making the system unresponsive while backups were being made. I have no idea why this is but a few other people have reported the same thing.

Thinkpad close calls

(I am not on Lenovo's payroll, just a happy user.)

I just got a new Thinkpad X201, and will comment on it more in due time. But while I was waiting for it to arrive, something happened that reminded me why I don't have to think twice about buying or recommending Thinkpads.

A friend of mine had spilled a glass of water on her Thinkpad. Well, Thinkpads have drainage holes under the keyboard so the bulk of the water is routed harmlessly out of the bottom. So this was a minor incident. The laptop wouldn't boot for about a day. But once it had dried off, it was back in business. No prepaid shipping box, no trips to the repair store. No discernible lasting damage. None.

Water damage must be one of the most common causes of laptop death. And yet, most computers (Thinkpads excepted) ship with a keyboard that goes zap when you spill something on it. It is astonishing that the spill-through keyboard (or equivalent) is not a standard feature on laptops. It does significantly increase the expected lifetime of your computer.

And it's not just water damage, either. My own X61s has also been through quite a few nasty drops and falls. I fell on it once when I slipped on ice. No ill effects. For the laptop, anyway. And the thing is everyone just expects that level of durability from Thinkpads. There is some serious quality engineering going on at Lenovo.

For crying out loud, the Thinkpads pass the freaking military spec tests for ruggedness. And just for fun, here's a video of a guy driving a motorbike over a Thinkpad.

These things are unbelievable. They are really built to last.

Google Web Toolkit again

Google Web Toolkit 2.0 was released some months back. As I've said before, I think GWT or something like it is really the right way to write web apps. The optimized/compressed/inlined Javascript you want to be running in any nontrivial web app is so far from the readable and modular code that you want to actually be writing that it really demands an intermediate translation layer. This most recent release really just cements that fact.

For example, new in GWT 2.0 is code splitting, a feature that helps to reduce page load times. You define some split points in your app— points during execution where the client can make a round-trip to the server to fetch more code. GWT breaks off parts of your application that aren't needed when the app initially loads, and only downloads them when the app needs to cross the split point. Sure, you could compute, by hand, the transitive closure of all the components of your application that aren't past any split point, and shuffle your code around between files, and dread having to redo all that every time you do some refactoring. But you have better things to do.

It's true that Javascript engines are getting faster every week, so the value of highly optimizing your Javascript ahead of time may seem rather uncertain. But GWT also does things like automatically creating image sprites on your behalf, so your app can pull down all its images without the overhead of multiple HTTP requests. No Javascript engine can make excessive image requests fast. And in version 2.0, GWT does something similar for stylesheets. Again, all stuff you could do by hand— if you were highly disciplined, or a robot.

Further reading: More new features in GWT 2.0 and stuff slated for 2.1.

Assorted Notes

Many random notes (some for my own reference), each of which is too short to warrant a full blog post:

PSA: remote tab completion

If you have set up passwordless SSH login to some host, then bash-completion in Debian/Ubuntu (which is enabled by default, I think) automatically completes remote paths as arguments to scp. For example, pressing TAB after the following does exactly what it ought to, namely, display files within /path/to/whatever on the host example.com:

scp example.com:/path/to/whatever/
Emacs: dired-jump

Ever find yourself wanting to rename or move a file while you're editing it? M-x dired-jump brings up a dired view of the directory containing the current file (you may need to (require 'dired-x) first). Press R ("Rename") and type the new path.

The best part is that the original editing buffer gets its path updated automatically (and its buffer name too, if you changed the basename), so you can get straight back to work— no need to close and reopen the file.

Suspending from the command line

On Ubuntu 10.04 Lucid, you can suspend the machine programmatically by installing acpitool and then running the following:

gnome-screensaver-command --lock # Optional- locks the screen
sudo /usr/bin/acpitool -s

To avoid having to enter my password every time for acpitool, I whitelisted that command in sudo for use without a password. You can do this by running sudo visudo and adding the following line at the end of the file:

%admin ALL = NOPASSWD: /usr/bin/acpitool -s

Sources: Linux Living. Also see: instructions for previous Ubuntu versions; pm-suspend(8).

VirtualBox

I've been using VirtualBox (aptitude install virtualbox-ose) to run virtual machines of various GNU/Linux flavors (for me, it's primarily useful for making sure Zeya works on different platforms and configurations), and I am generally pleased with it. A couple of tips for setting up VMs for maximum effectiveness:

  • The virtualbox-ose-guest-x11 package, when installed on the guest, provides a driver for the virtual display device. This seems to be necessary (and sufficient) to get not-crappy graphics performance.
  • Configuring your VM to use bridged networking makes the VM appear as a device on the host's network, for example, it will pick up an IP address from your local DHCP server.