Humility

Paul Buchheit, Google employee #23:

I wrote the first version of Gmail in one day. It was not very impressive. All I did was stuff my own email into the Google Groups (Usenet) indexing engine. I sent it out to a few people for feedback, and they said that it was somewhat useful, but it would be better if it searched over their email instead of mine.

And another nice bit, from an earlier post about undo:

…one comment that was so remarkably wrong that it brightened my whole day:

While an Undo feature could be useful, isn’t this just coddling people who should otherwise be paying closer attention to what they are doing? A mistake is a mistake, and people need to learn to live with the consequences of the mistakes they make.

This comment may have been a joke, but I really like this “tough love” approach to usability, because in just a few words it perfectly captures the exact opposite of what we should be doing.

To design great products, we must truly empathize with our users, and understand that if they are having problems using our products, is more likely our fault, not theirs.

…[T]he more we can lower the costs of making mistakes, the faster we can move.

Java vs. C#: More fun with initializers

Or, proof by example that C# isn’t just Java with different capitalization conventions.

On the heels of Neal Gafter’s ice cream puzzler we have the less closure-rific but still interesting “Why do initializers run in the opposite order as constructors?” from Eric Lippert. Here’s my Java version of Eric’s C# code:

class Foo {
	public Foo(String s) {
		System.out.printf("Foo constructor: %1$sn", s);
	}
}

class Base {
	private final Foo baseFoo = new Foo("Base initializer");

	public Base() {
		System.out.println("Base constructor");
	}
}

class Derived extends Base {
	private final Foo derivedFoo = new Foo("Derived initializer");

	public Derived() {
		System.out.println("Derived constructor");
	}
}

class Program {
	public static void main(String[] args) {
		new Derived();
	}
}

I’ll spare you the suspense and just print the answer — the Java answer, that is.

Foo constructor: Base initializer
Base constructor
Foo constructor: Derived initializer
Derived constructor

Whereas the C# code equivalent of the above, Eric’s original, prints:

Foo constructor: Derived initializer
Foo constructor: Base initializer
Base constructor
Derived constructor

What’s going on?

The Java code does this because when a Java object’s initialized the JVM works its way down through its superclasses, starting at the root (that is, Object), and for each class first runs the initializers, then the constructor. This can have some wacky side-effects. For instance, sooner or later everyone gets the bright idea to define an abstract method in the base class and call that method from the base class constructor — which works fine until some subclass’s concrete implementation depends on a field that’s only initialized in that subclass, and suddenly you’re getting NullPointerExceptions in impossible-looking places.

This happens whether the field’s initialized in the subclass constructor or in a subclass initializer, and while it’s fairly obvious what’s going on in the constructor case, it’s a little more confusing the first time you have, say,

private final long timestamp = new Date().getTime()

come out 0 (or null, if you use a capital-L Long) when you know your clock’s not set to January 1st 1970 — and then later on come out 1203338390828 or whatever, even though final fields are supposed to be immutable.

The constructor case, I think we’re stuck with. The initializer case, though, the folks at Microsoft apparently decided they were sick of. So C# instead runs all the initializers in reverse order (subclass to superclass), and then runs all the constructors (in the order you’d expect). This means final fields in C# really are final, or rather, readonly fields really are read-only — they’ll only ever have one value, no matter when you look at them. [Looks like I didn’t have that quite right — see Eric’s comment below.]

Now I wonder what happens in ActionScript? The Adobe folks claim my const bug in FlexBuilder is fixed; I’ll have to download the latest build and see.

Comments closed due to spam.

Downtime

The colocation people housing the discontent.com / chrononaut.org / allstarstories.com server decided that the right response to a faltering economy was to double their rates, and my kindly host Brandon decided that the right response to that was to take his business elsewhere, so we’ll be moving this week — down Monday, hopefully up again by Wednesday, but one never knows. Anyway, if you can’t reach this site or at any of my non-gmail email addresses, that’s why.

Color-flavor locking breaks chiral symmetry

(Attention conservation notice: Post not actually about quantum chromodynamics.)

If you listen to the Q&A for Josh Bloch’s Closures Controversy talk at JavaPolis, you’ll hear me ask a silly question around minute six — namely, whether Josh should see the BGGA closures proposal as a benefit rather than a hazard, on account of the material they’ll provide for the Java Puzzlers he and Neal Gafter are so fond of. Well, it looks like Neal’s getting a head start with “Closures Puzzler: Neapolitan Ice Cream.”

This looks like a good opportunity to stretch my brain, and also try out the fancy syntax highlighter that Rahel discovered. Let’s see how it goes.

Here’s the puzzler. What does it print?

enum Color {
  BROWN(Flavor.CHOCOLATE),
  RED(Flavor.STRAWBERRY),
  WHITE(Flavor.VANILLA);

  final Flavor flavor;

  Color(Flavor flavor) {
    this.flavor = flavor;
  }
}

enum Flavor {
  CHOCOLATE(Color.BROWN),
  STRAWBERRY(Color.RED),
  VANILLA(Color.WHITE);

  final Color color;

  Flavor(Color color) {
    this.color = color;
  }
}

class Neapolitan {

  static  List<U> map(List list, {T=>U} transform) {
    List<U> result = new ArrayList<U>(list.size());
    for (T t : list) {
      result.add(transform.invoke(t));
    }
    return result;
  }

  public static void main(String[] args) {
    List colors = map(Arrays.asList(Flavor.values()), {
      Flavor f => f.color
    });
    System.out.println(colors.equals(Arrays.asList(Color.values())));

    List flavors = map(Arrays.asList(Color.values()), {
      Color c => c.flavor
    });
    System.out.println(flavors.equals(Arrays.asList(Flavor.values())));
  }
}

Now, right away we can see there’s something suspicious going on here with the order of initialization — Color requires Flavor and Flavor requires Color; who wins? This is the sort of question I probably should be able to answer, but in practice can never remember until I see a symptomatic bug. So let’s find a symptomatic bug:

for (Color c: Color.values()) {
  System.out.println(c + ": " + c.flavor);
}

for (Flavor f: Flavor.values()) {
  System.out.println(f + ": " + f.color);
}

Result:

BROWN: CHOCOLATE
RED: STRAWBERRY
WHITE: VANILLA
CHOCOLATE: null
STRAWBERRY: null
VANILLA: null

Say what now?

But if you think about it, it makes sense. Color is declared first, but because Color requires Flavor, Flavor is actually initialized first — so when you get to, say, CHOCOLATE(Color.BROWN), well, Color hasn’t been (can’t have been) fully initialized, so Color.BROWN is null.

At this point I’m tempted to just say my answer is:

false
true

…but let’s make sure there isn’t more to it than that. So far I’ve been too lazy to download and install the BGGA closures prototype, so let’s see how hard it is to fake this in straight Java:

class Neapolitan {

  static interface Transform {
    U invoke(T t);
  }

  static  List<U> map(List list, Transform transform) {
     List<U> result = new ArrayList<U>(list.size());
     for (T t : list) {
       result.add(transform.invoke(t));
     }
     return result;
  }

  public static void main(String[] args) {
    List colors = map(Arrays.asList(Flavor.values()),
      new Transform() {
        public Color invoke(Flavor t) {
          return t.color;
        }
      });
    System.out.println(colors.equals(Arrays.asList(Color.values())));

    List flavors = map(Arrays.asList(Color.values()),
      new Transform() {
        public Flavor invoke(Color t) {
          return t.flavor;
        }
      });
    System.out.println(flavors.equals(Arrays.asList(Flavor.values())));
  }
}

Well, that didn’t seem so hard — what do we get?

true
false

Say really what now?

Let’s put a print statement in that map() method and see if we can figure out what’s going on.

  static  List<U> map(List list, Transform transform) {
     List<U> result = new ArrayList<U>(list.size());
     for (T t : list) {
       U u = transform.invoke(t);
       System.out.println(t + " => " + u);
       result.add(u);
     }
     return result;
  }

. . .

CHOCOLATE => BROWN
STRAWBERRY => RED
VANILLA => WHITE
true
BROWN => null
RED => null
WHITE => null
false

Holy late binding, Batman! The order of initialization’s reversed!

And I think I know why. To demonstrate, let’s take those original print loops and reverse them:

for (Flavor f: Flavor.values()) {
  System.out.println(f + ": " + f.color);
}

for (Color c: Color.values()) {
  System.out.println(c + ": " + c.flavor);
}

. . .

CHOCOLATE: BROWN
STRAWBERRY: RED
VANILLA: WHITE
BROWN: null
RED: null
WHITE: null

And behold! we get the same effect:

Why? Because classes are loaded at runtime. I said up there that Color required Flavor, and I was right. But whether Flavor or Color is loaded first has nothing to do with declaration order, and everything to do with which one happens to get called first in the code. Call Color first (as in the first set of print loops), and Flavor gets incompletely initialized; call Flavor first (as in the second set of print loops, and in the puzzler itself), and it’s Color that suffers.

(Note that the List<Color> reference doesn’t count — generics are erased at run-time, so at run-time when the JVM gets to the declaration of colors, it’s just a plain old untyped List. The Flavor.values() call is the first time one of these classes actually gets loaded.)

The moral of the story? If you ask me, it’s — as with so many of these — don’t code like this. 🙂 But also: just because that enum variable looks vaguely constant-ish doesn’t mean the compiler’s going to inline it for you, and if the compiler’s not going to inline it for you, you have to think about how the code behaves at run-time.

Mostly, though, just don’t code like this.

(Now, I just hope, in the name of the Knights of the Lambda Calculus, that bringing in BGGA closures doesn’t change the answer…)

(Update: Neal’s posted some solutions, encapsulating flavor and color and deferring the resolution till run-time; worth a look.)

Comments closed due to spam.