Cryptics

In posting messages about the new for-each loop syntax in Java 5.0, many developers have complained about its crypticism. A for-each loop might look like:

for (Employee employee: department)
 terminate(employee);

You would read this for-each loop as, “for each employee (of type Employee) in department).” Many developers would have preferred something like:

for (Employee employee in department)
 terminate(employee);

But alas, Sun resists new Java keywords like “in” because they have the potential to break gobs of existing code.

It’s not that big a deal to me, since I view the loop construct as idiomatic. Once I saw it and it was explained to me, or perhaps twice, it became ingrained. Subsequent encounters required no such explanation or even translation time.

Nonetheless, the new for-each loop is a slightly cryptic construct. Not quite as bad as the ternary operator (conditional ? true-value : false-value), but still not obvious the first time. Some developers can’t stand it.

My take is that Java is a fairly cryptic language to start with, particularly if you have no background in C-based languages (C, C++, Objective C, C#, and whatever else). The old C-style for loop isn’t obvious either. Typical C code is rife with odd characters such as *, %, &, {, }, and |.

This obvious observation led me to create Jeff’s hypothesis of cryptics:

Jeff’s Definition of Cryptics: The crypticism of a language is directly proportional to the mean number of shift keystrokes required.

It’s a pretty useless definition, granted. But taking a look at a couple languages that appear on opposite ends of the spectrum shows that there is some validity. Curly braces in C-based languages { use the shift key, as does * (pointer dereference). The new generics stuff in 1.5 uses angle brackets < and >, both requiring use of shift. The tertiary operator uses both : and ?. Strings are set off by use of the ” character. And C uses lots of parentheses.

Smalltalk, in contrast, uses brackets ([ and ]) to set off blocks. No shift-combination necessary! Boolean operators are spelled out instead of using & and |. Strings are set off by use of the ‘ character. The major exception to the rule is the use of the colon to designate a selector (but this also suggests that perhaps you should pass fewer parameters to your methods).

Of course, crypticism is related to how easy it is to read text, not write it. But it’s no coincidence that the cryptics require shift-combinations on a standard keyboard or typewriter. These are the characters that make things difficult to read when used to excess.

I was curious enough to pose the idea to Dan Ingalls, who had a lot to do with the design of early Smalltalk implementations. He indicated that indeed there was a conscious effort to reduce the number of shift keystrokes required. This was due to the fact that one goal for Smalltalk was that children would be able to program in it.

Lots of shift-key combinations = lots of crypticism. I’m still amazed at the fact that modern languages retain so much of the unnecessary constructs and ugliness of a language that is 30 years old.

Performance Debates

I’m always amused at the number of posts I see in Java forums about various performance concerns. Yesterday I read a sequence of anxious messages discussing whether Java’s import pkg.* performs worse than importing explicit classes. Once people were informed that it makes no difference at runtime, the concern moved to compile time.

Java compilation is slow, but it’s not that slow, and it’s also not C++, where concern over such minute detail can be rewarded handsomely. I think we’re talking close to picoseconds here. Someone did manage to run a time test and found a difference that equated to probably one minute over the course of a development year.

I find it odd that people are willing to waste hours debating this nonsense. Worse, they’re willing to sacrifice far more hours by sacrificing readability for execution efficiency.

I figure the anxiety over performance is due to two things: one, Java is one of the slower compiled languages out there (scripting languages such as Python typically fare much worse). Two, it’s something you can quantify easily.

With respect to the first concern, if you have that much angst over performance, perhaps you shouldn’t be programming in Java. Honestly, it’s not *that* bad, and plenty of systems execute with high performance while ignoring some of the minute optimizations that Java affords (for example, making all possible methods final). And usually, the concerns are misdirected. Some people even worry about performance when there are no known performance issues. But all it takes is a profiler (such as JProbe or OptimizeIt) and a bit of education to get the seance aspect out of performance optimization.

It’s the quantification that’s most alluring, however. Geeks like to speak numbers, or more importantly, they like to rank things. “Star Trek is better than Star Wars,” and “this construct executes faster than that.” Quantifying good programming style, however, isn’t possible. It’s subjective and debatable, so it doesn’t provide such an easy answer.

Get over it. Code for cost. The cost is in maintenance, and usually not in degraded performance. That means coming up with an optimal design–one where you can easily make performance tweaks if and only if you find performance problems. A bad design with bad performance will cost far more to fix than a good design with bad performance.

Not to say that you should ignore performance entirely, either. But right now my major concerns over performance aren’t about the production system’s performance. They instead are about the performance of my unit tests–something that directly ties to the cost of maintenance.

Atom