E-Mail Volume

After my two week vacation, I had 2000 unread e-mails. Sounds like a lot, but twenty years ago after a three week honeymoon, I had 3000 unread e-mails. I guess I’ve been dealing with a lot of e-mail for a long time.

What was hard to get through was the 600 unread items in newsfeeds. It took a week of spare time reading to get those under control.

Mac Software That I Run

Since Marc Andreeson posted his Killer Mac OS X apps for 2007 and someone just asked me, I’ll post some of my favorites.

NetNewsWire: go ahead and pay the $30 for the non-Lite version. This is a great newsreader. Do this and you’ll understand why websites carrying any sort of news (and ads) are effectively dead.

MenuMeters: for some reason, I just can’t live without a CPU graph in the menu bar. I’ve been that way every since I fired up xload in X10R3. MenuMeters also can show a handy Tx/Rx network traffic meter. That lets me know when my DSL has down-shifted. Again.

MarcoPolo: is an automatic location switcher, a better-thean-before replacement for the OS 9 Location Manager. After only six years. It is supposed to switch my default printer, but that isn’t working for me. There are some other tools like this, and the MarcoPolo home page lists them with a chart showing their features.

SQLGrinder: I use this for running Oracle queries. Not a lot of features, but it works fine. Like other tools, it is pretty clueless about CSV format, so I use keyboard macros in the next tool to quote text strings that contain commas.

Emacs: either you need this or you don’t know you need it. I’ve tried AquaMacs, but it was too Aqua and not enough Emacs. I’m running Carbon Emacs.

Fire: this is my multi-protocol IM tool. Everyone else seems to like Adium, but I found it too pixel-greedy, too cute, and too quacky. They are both free, so make your own choice. Hmm, according to Wikipedia (it must be true!), there will be no more versions of Fire. It still works for me, so I’ll wait until I must switch.

Fetch: an FTP client. Fetch goes back to the early days of Mac shareware. When I got a Windows machine at work, I figured that Windows shareware was as good as the Mac stuff. I never found a Windows FTP client nearly as good as Fetch, either free or commercial. There are plenty of good Mac FTP clients, but Fetch hasn’t failed me in over a dozen years, so there is no point in changing now. Yes, it is all rewritten to be OS X native.

MarsEdit: if you post to a blog, consider getting a client. It is way faster than dealing with the web posting interface. MarsEdit is a good one, it is on Andreeson’s list, too. Ecto also has fans and seems to have a better UI for uploading images.

GraphicConverter: kinda old school, but iPhoto drives me up a wall and GraphicConverter does what I need. Plus, I’m set if I ever need to read images in Amiga HAM or LuraWave or Meteosat 5 or X-Face (see list of supported formats).

Mouseposé: perhaps the most focused app I’ve ever used, this puts a spotlight around your cursor for doing demos on a projector. That’s all it does and it works great. They’ve gone payware and added some other features. Next time I do a demo, I’ll spend the $14.95.

SubEthaEdit: a multi-user text editor. I don’t use it that much, but it is so ideal for distributed note-taking that I bought it.

Apple and High Standards

At work, we had an e-mail discussion about this New Yorker article on feature proliferation, and one of the strands was about a mis-understanding in the article, specifically that Apple Design equals Simple Design, especially with the iPod. Among the various good observations — “simple is hard”, “sexy supports simple” — I chipped in with the following.

There is a weird follow-on effect that makes the best Mac software vastly better (or at least better-looking) than supposedly equivalent stuff on Windows or Linux. For example, Microsoft’s Mac e-mail tool (Entourage) is much nicer than Outlook.

Even more odd is the case of NetNewsWire, an RSS reader. It has been around for nearly five years, but no one has even managed to copy it on Windows, let alone surpass it. WTF? How hard can it be? Do Windows developers just not pay attention?

In some sort of cosmic synchrony, Tim Bray posted a one-paragraph shout-out to NNW today. Tim is Sun’s Director of Web Technology, the driving force behind Atom, and a really nice person. Heck, it ain’t that long, I’ll quote the whole thing:

The problem is, these days, that my input queues are jammed up. I’m reading Caesar: Life of a Colossus by Adrian Goldsworthy and it’s very good, but it’s awfully big and thick and dense. And my time for reading is tight because, after all, I’m married with two children and also I’m trying to read the Internet, or at least that huge little piece of it where people care about the things I do. And on that subject, once again I just have to plug NetNewsWire. I’ve tried a ton of newsreaders on a ton of platforms. Google’s blog reader is pretty good, and so are a couple of the other clients, but NetNewsWire just shows you more stuff in less time with fewer keystrokes. Years ago I predicted that feed-reading would have been sucked into the browser by now, but I was wrong. So between that and Caesar, and day-to-day job work, and a grungy unexciting complicated fill-a-hole-in-the-ecosystem programming project, well, I have Wikinomics and Everything is Miscellaneous and RESTful Web Services and the Programming Erlang PDF staring accusingly at me from the shadows. Blame Julius Caesar and Brent Simmons.

NetNewsWire rules. It is vastly better than anything else I’ve tried, including Google Reader.

One of the reasons I use a Mac is to keep my standards high. If my work is “as good as Windows”, it isn’t good enough.

Templates and Website Design

John Gruber posts about templates and design on his excellent blog, Daring Fireball. He talks about specific blogservers, but the point is true for any serious website.

I started the visual design with a blank sheet of paper, and then moved on to an empty Photoshop file. I designed the markup starting with an empty XHTML 1.0 skeleton in BBEdit. I designed the URLs on pen and paper, trying to maximize clarity and structure while minimizing cruft and length.

On the other hand, anyone who’s designed a software library is well aware that 90% of their customer’s shipping code has some chunk that was written by loading up the sample program in an editor. When I was working on ORBlite, it was pretty easy to tell who had used my sample code and not replaced the default log message (“Oops, an error occurred.”).

So, I disagree with John a bit. He makes the right qualifications for his recommendations (“… for anyone attempting to establish their own unique brand”), but that is a tiny fraction of websites, though a larger fraction of traffic.

There are plenty of websites that should be usable, attractive, and functional (utilitas, venustas, firmitas) without a ground up design. Said differently, the default templates need to be excellent, with a set of base styles broad enough to serve as useful starting points for various tastes. Even those tastes that design MySpace pages.

As John says at the close of the article, “If you start with nothing, you’re forced to think about everything.” For a designer, that’s great. For the rest of us, not so good. For good or ill, most templates aren’t that far from “nothing”.

To be specific, I’d like one, just one, template for Movable Type 3.x that has a fluid width.

Five Habits of Seven Successful Websites

Aaron Swartz calls his post Seven Habits of Highly Successful Websites, covering five approaches common across MySpace, Wikipedia, Facebook, Flickr, Digg, del.icoi.us (I can never type that correctly), and Google Maps. I guess that the sixth and seventh habits are “get the details wrong” and “always use magic numbers”.

The five are:

  1. Be Ugly
  2. Don’t Have Features
  3. Let Users Do Your Job
  4. Ignore Standards
  5. Build to Flip

Welcome to the real Web 2.0.

Design for Easier HTTP Load Testing

I’ve told two people about this trick in the last few days, so it is worth writing it up.

It is hard to get a good distribution of requests in your HTTP load tester, it usually requires a knowledge of valid keys or users and a model of the distribution of the accesses. This can all be built in the load tester, but that seems to be a big barrier, since I’ve rarely seen that happen. I’ve certainly never done it and I’ve needed it several times.

The easy way to do this is to add a “random choice” parameter to the app. The app already knows the legal set of keys or users and can quickly make a choice. You already know the language and the code in the app, and the changes are localized to the URL parameter parsing. Let’s say you have a back-end server that returns records.


An HTTP load tester can access the single randomizing URL over and over again, and fetch different records each time. This is a trivial load test script. In Jakarta JMeter, it is one of the samples.

This is really very easy to write inside of the server. Getting a random key looks something like this, assuming that we already have an instance of java.util.Random initialized and ready to go.

key = cache.keySet().get(random.nextInt(cache.keySet().size()))

In Python, you can use the default, shared instance of the random source and the choice() convenience method:

key = random.choice(cache.keys())

This can all be done in the code that parses the URL parameters. Once you have a random key, the remainder of the app executes with no changes.

If the app should be tested with a non-uniform distribution of accesses, that is also easy to do. Python’s random.paretovariate() looks especially good for Zipf (80/20 or “long tail”) distributions. Or you could duplicate that code in your favorite language:

def paretovariate(self, alpha):
"""Pareto distribution.  alpha is the shape parameter."""
# Jain, pg. 495
u = 1.0 - self.random()
return 1.0 / pow(u, 1.0/alpha)

For user logins, add an option to masquerade as a random user, or even a random user from certain classes (big profile, frequent login, new user …).

For testing search, I once made an especially fancy tester that would access a log of queries in order, but start at a different place for each client. This preserves the time locality of queries while giving each client a different set. I used a cookie to hold the per-client state, so that each client would access the queries in order from their starting place. It went roughly like this:

  1. If the client did not send a cookie, choose a random index in the log.
  2. Otherwise, read the cookie to get an index.
  3. Set the cookie to the next index.
  4. Wrap the index, modulo the log size.
  5. Run the search with the query at that index.

Now go test your software. I might need to use it someday.


FORTRAN turns 50 years old in four days. October 15, 1956 was the release date for Programmer’s Reference Manual, The FORTRAN Automatic Coding System for the IBM 704 EPDM (6.1 Meg scanned PDF). FORTRAN was an amazing achievement, inventing the idea of a compiler while generating code as fast as hand-coded assembler.

There are a couple of early papers that give a feeling for how hard all this was. The FORTRAN Automatic Coding System (1957) describes the design of the compiler. History of FORTRAN I, II, and III (1978) goes into the economics of computing at the time, influences, design decisions, and follow-ons. They didn’t have it really working until April 1957, which seems rather similar to modern software projects.

Some possible ways to commemorate this occasion:

  • Use no words longer than six chars.
  • Propose the arithmetic IF as a Java extension.
  • Use GO TO. A lot.
  • Number your statements.
  • Refer to the LEDs on your computer as “sense lights”.
  • Solve a problem that uses only 32K 6-bit words of memory. Data and program has to fit.
  • No indentation.
  • Switch to vacuum tube heat this winter.
  • Write a program on a coding form, type it in, and run it. If there are any errors, even syntax errors, start over.

Prepare for the festivities by (re)reading the Programmer’s Reference Manual. It is only 51 pages, and refreshingly clear. The whole language fits in your head — no running back to the manual to figure out why const is propagating through your templates like a virus or whether you should use notify or notifyAll.