Why I hope Amazon’s Kindle succeeds.

At Daring Fireball, John Gruber hopes that the Amazon’s Kindle fails because the books being sold by Amazon are wrapped in DRM and cannot be loaned or reasonably transferred to another format.

I appreciate and understand his misgivings. I really do. I have three walls full of books which is evidence of how much I appreciate the power of the written word. And there are some books which I hope will always remain in book form which, in my opinion, are timeless: mathematics and mathematical reference books, books on algorithms, classical books on philosophy–all of which deserve to be presented on the printed page, and saved and cherished like a fine wine which can be endlessly savored without the bottle ever going empty.

But to me there are three classes of books, and (pardon the heresy that I’m about to speak) only one of which deserve the permanence of the printed page. There are timeless works: Donald Knuth’s “The Art of Computer Programming” for example, which deserve to be printed on paper and bound in a book.

Then there are ‘trash’ entertainment novels; books which will be read for enjoyment and, chances are, stored in a basement until they are rediscovered years later soaked through by a water leak, occupying space which could have been used by something else.

And there are ‘reference’ books: technical books which describe a technique, programming API, chip set, or other thing which will find itself out of date perhaps a half dozen years from now.

For the first type of book, yes: I want to own them in book form. I want to put them on my bookshelf on display, take them down and refer to them. They speak volumes as to the type of person I am and the type of person I hope to be, and they are books I hope to pass on when I no longer need them. My copy of Aho, Sethi and Ullman’s “Dragon Book” contains information which was valid twenty years ago and will be valid twenty years from now–even when new techniques are invented which improve on the basic design. Knuth’s books are also essentially timeless, even though today most modern programming languages incorporate many of the algorithms as part of a standard run-time library, if only so one can know how these things work. Numerical Recipes will always be useful.

But there are a number of other books which are not so timeless. Any book on writing software for MacOS 7 is simply a waste of paper and, the dogma that all books are timeless and important aside, really richly deserves to be turned into pulp and recycled into drink containers for fast food restaurants. While my copy of Logic: Form and Function is still quite useful after being first published nearly a half-century ago, my copy on the pre-election biography of George W. Bush (published in early 2000) was a waste of shelf space and was recycled years ago. And who really needs a book on Windows 3.11 software development and using DDE for exchanging messages between top-level windows?

So the concern that John Gruber has with respect to the Kindle may be well founded–but there are quite a few “disposable” books out there that really are ephemeral–and if they were to disappear a decade after they were published, would probably never be missed other than by those people who like collecting obscure historical footnotes.

Why Observable/Observer Should DIE!

I’m not talking about the design model here, but the java.util class and interface. From a development standpoint the interfaces should die a painful death and here’s why:

(1) It violates the rule of discovery–that a newbie to the code should be able to discover easily what is going on. If you’re maintaining some code and you need to change the object you’re passing to notifyObservers, because the object being passed is a generic Object, you have no good way to discover which Observers would be affected. Two different Observers will have the exact same interface–but one may be affected while the other is not. You have no good way to figure out through simple search which observers are observing which observables.

(2) Like the dreaded ‘GOTO’, it makes it easy to write spaghetti code. One of the bad habits in Java is for people to create inline anonymous classes to handle events and state changes–and while this makes the original author’s life easy, it makes figuring out what little ‘classlet’ or snippet of code functionally belongs to another chunk of code. You may have a toolbar with five different buttons which seem functionally related–but the code which processes the contents may be scattered throughout your code.

This ability to create little anonymous inline classlets of functionality is Java’s equivalent to the GOTO: easily abused, it creates spaghetti code real quick. And observers simply encourage this practice.

(3) It potentially introduces event order dependencies. While an observer should preferably be used to update an unrelated element when a state changes–such as highlighting the ‘window dirty’ icon in a document window, in many cases I’ve encountered the observer object is used as a sort of “cross-cutting” functionality enabler–with cross-cut functionality added in a way which creates hard to understand dependencies.

I’ve got one class here where the notification creates a state change which later code in the observable depends upon. In other words, the observable depends upon the state of the observer to change before the observable can continue: fail to register the observer, and the observable fails.

It’s the dreaded GOTO all over again, except worse: it’s data driven GOTOs…

Anti-Patterns: Roll Your Own

Not quite the class inheritance error I had originally planned to write about, but something that is currently biting me in the ass.

The project I’m working on uses a Java Swing table. The way they use the table is, um, “unique” in that “Oh My God What Were They Thinking!” sort of a way. The fundamental problem here is that rather than using the existing Swing class and interface hierarchy in order to create a new table model to feed a JTable object, they instead rolled their own code that sort of kinda uses the JTable stuff, but in their own unique way.

They have their own ‘model’ object, for example, which doesn’t have anything to do with the TableModel interface in Swing, and which uses their own ColumnSpecification class–which again has nothing to dow with the TableColumnModel interface in Swing. Perhaps once I wade through this pile of code I’ll find that their way is more streamlines and more efficient to the task at hand. But right now, none of the stuff makes any sense. I even found one case where they appear to be using a table model object as a ‘flyweight’ table object–which makes no sense, as there are only two tables here.

At home I’ve been tinkering with a piece of code which creates a database connection to a remote SQL server and runs a whole bunch of queries in parallel. I came up with what I thought was an extremely clever way to queue requests up into a pooled connection manager which would pull my requests off and run the request by translating it into a SQL query in one of several pooled background threads.

I plan to rip it all apart.

Why? Because there is an accepted way to do J2EE cached connections and cached prepared statements–and while my design is probably fairly clever, it also doesn’t do things the way it’s normally done in J2EE world with a DataSource object obtaining connections from the database.

And that’s the anti-pattern: rather than sort your way through a whole bunch of puzzling interfaces and use the accepted pattern that the designers of a class expected you to use when writing SQL queries or creating JTables in Swing, you instead decide to roll your own. While your creation may be quite solid and impressive–because it’s not the standard way to do things the next maintenance developer to come along will bang his head against a brick wall trying to sort out what you did while you move on to create new ‘self-rolled’ anti-patterns elsewhere.

For me, what should have been a 30 minute change to their source base–adding two new columns which can be dynamically turned on and off as needed–has turned into a three day nightmare of wading through foreign (and completely unnecessary) class hierarchies and odd-ball problems, such as the apparent abuse of the fireTableStructureChanged() method to indicate a request to change the structure rather than a notification that the structure has changed.

Many years ago Apple had a technical note describing this very problem. They called the problem a failure to understand not just a particular interface, but also a problem to understand the “Gestalt” of that interface. You may be using the interface in a way which accomplishes what you want–but if you don’t use the interface in the way it was intended to be used (because you don’t understand the gestalt of that interface)–you may be screwed heavily later on down the road.

Sun provides a number of Java tutorials on the different Swing components–including tutorials on the JTable class. What these tutorials are good for is not in learning how to build a table–someone could in theory roll their own table class without ever touching the JTable class–but in learning the gestalt of the existing table implementation.

And even though you may not run into dire problems by not understanding the gestalt of an interface (Apple’s tech note was dealing more with interface abuse, such as reaching into a memory handle and fiddling the bits there in a way which was documented as private–but documented nonetheless), you will make the maintenance programmer’s (or you, six months or a year later) life a living hell.

What’s wrong with Safari for Windows

Much has been made about Safari for Windows looking like hell.

Here’s my take, as a Mac fan: it looks like hell.

Here’s what’s wrong:

(1) The Gamma on Microsoft Windows is considerably darker than on the Macintosh. To review, the gamma is essentially the exponent used to adjust the color (from 0 to 1) for display. Windows monitors use a gamma of 2.5, while Macintosh systems (which were targeted towards graphic artists) use a gamma of 1.8, which is similar to that of paper. This means that for a middle gray of 50% (0.5), the resulting luminance on Windows is 0.176 (=0.5^2.5), while on the Macintosh it is 0.287 (=0.5^1.8). The eye, like all organs on the body being sensitive to the log of the energy rather than being linear, detects 0.287 as roughly “half as bright” as 1, and perceives the 0.176 lumanence level as darker.

Now it appears Safari was ported by creating a packaged version of the Cocoa libraries to run on Windows–and it appears Apple’s engineers have not gamma corrected for Windows. This means the Safari window looks depressingly darker than the same window on the Macintosh.

(Sadly this would be an easy fix: a 256-byte array mapping from Mac RGB levels to Windows would help make the window ligher and more ‘natural.’)

(2) Because it is darker, Apple’s carefully tuned font anti-aliasing technology, which they also ported to Windows, looks like hell: the letters look heavy and unnecessarily bolded.

(3) Because Safari uses essentially Cocoa on Windows, it doesn’t do a few things correctly–like allowing resizing of a window by grabbing any edge or corner. Instead, Safari only allows resizing the window by grabbing the lower left corner. The result is a window that doesn’t behave like any other window on the screen.

Oh, and to address Joel’s concern about the initial startup time of Safari: on the Macintosh, when I installed the 3.0 beta, I experienced a nearly two minute delay before Safari started for the first time. I suspect Safari was doing a hell of a lot of book-keeping behind the scenes–which apparently needed to be done only once. So like Safari on Windows, the first time you start up the beta, it takes for freakin’ ever to start. The second time–just a few seconds, as usual.

Welcome to Hell.

Me: I’m just interested in getting a local sandbox going on my dev box so I can build your component, that way I can scope out the level of effort needed to make our recommended changes.

Them: I don’t understand, you want to make changes to the dev build?

Me: I just want a local sandbox; I don’t want to check anything in. That way I can better understand the code.

Them: Uh, that’s not the way it works.

Me: Huh?

Them: When a developer wants to make a change to our component, they first check out the file, edit it, then check it back in. Then a nightly build recompiles the product and deploys it on a test harness where, after the nightly runs, the product is smoke tested to make sure there are no problems. Of course a developer can trigger the build process manually if they need to; this triggers the nightly to run early.

Me: You mean there is no local developer sandbox?

Them: No; that’s the way our development process works. You check in your changes and our test harness compiles and verifies the changes work.

Found the sysdeo plugin on the French site.

*sigh*

If you search for the sysdeo plugin for developing Tomcat on Eclipse, you’ll find that every link in the blasted world points to the English site, which is now gone.

A little investigation and puzzling out some random french, and I found where it’s now located on the French site. Hopefully if anyone is setting up to do Tomcat development under Eclipse, and they want the Sysdeo plugin (trust me; worth its weight in gold), here is a link.