May 2004

« April 2004 | Main Index | Archives | June 2004 »


Say you're trying to drum up popular support for some ideal. One of the best ways to make me discount your cause out of hand is: a link to PetitionOnline.

This whole thing is wildly inaccurate. Rounding errors, ballot stuffers, dynamic IPs, firewalls. If you're using these numbers to do anything important, you're insane. -- The Slashdot poll page.

Does anyone really believe that any cause is going to be served by associating it with the kind of accuracy and balance of opinion associated with online polls? Remember that thing about how you should always send paper mail to politicians, because it proves you care enough to make more than a token three minute effort? That must apply several orders of magnitude more to online petitions. Anyone receiving such a poll would most likely think "It's just a bunch of wackos, and three guys from SomethingAwful voting a few hundred times each" and throw the whole thing out.

PetitionOnline is another one of those lazy options: "How can I convince myself I'm accomplishing something worthwhile, without more than two minutes effort?"

As such, I urge each and every one of you to sign my petition for the abolition of online petitions. You know it make sense. Please pass this URL on to everyone you know, so I can present this petition to PetitionOnline, and by the very logic that defines their existence, they'll have to listen! You can stop the rot! You can make a difference!

Monday Morning

  • 10:48 AM

There are two branches of Confluence development: the 1.0.x branch for patches to the released version, and the HEAD for everything that's going into the soon-to-be-released 1.1. Pretty straightforward so far.

So I sit down early on a Monday morning, assign an issue to myself from JIRA and start hacking. Neato, hibernate's ability to drop back to SQL can let me push some work the view was doing back into the database layer. I get the changes to the database layer done, drop back to make the necessary changes to the next layer up, and notice that some other changes I'd made last week just weren't there.

I was working on the branch by mistake.

Copy out some of the code I want to save, roll back the changes, close IDEA... oops, I just wanted to change projects. Oh well, open IDEA again, let's put that code where it should be. I get the changes to the database layer done, drop back to make the necessary changes to the next layer up, and notice that some other changes I'd made last week just weren't there.

There's a call on line two for Charles from a Mr Deja Vu. He says you left your brain at home, and would you like to pick it up?

It's like that game with the three cups, except there's only two cups, and one of them has this big black X on the top in permanent marker. And I still lost.

On Display...

  • 9:34 AM


Incorrect. You can still download [Movable Type] 2.661: after you download 3.0D via the Movable Type Free option, you can login to your TypeKey account and download 2.661. Not obvious, but possible.


Now I understand: it's like one of those fighting games where after you've finished it the first time, all the secret characters are unlocked.

Douglas Adams:

Prosser: The plans were on display.
Arthur: I eventually had to go down to the cellar...
Prosser: That's the display department.
Arthur: ... with a torch.
Prosser: Ah, the lights had probably gone.
Arthur: So had the stairs.
Prosser: But you found the notice, didn't you?
Arthur: Yes. It was on display in the bottom of a locked filing cabinet stuck in a disused lavatory with a sign on the door saying ‘Beware of the Leopard.’ Ever thought of going into advertising?

(Original thread)

On Comments

  • 7:40 AM

# A warm thankyou to everyone who told me to install MTBlacklist. I hadn't installed it before, because I had this vague recollection that it required source hacks, or a newer version of MT that I haven't installed, and that is no longer available.

It turned out neither are true. The de-spamming and bulk comment deletion features are pretty neat.

# Speaking of bulk comment deletion, here's the script I was using before I bit the bullet and installed MTBlacklist. Kudos to SixApart, the MT code is very well documented and readable, even for someone whose Perl hacking days are several years in the past:

unshift @INC, "./lib";
unshift @INC, "./extlib";

use MT;
use MT::Comment;

my $mt = MT->new();

my $iter = MT::Comment->load_iter();
my @blah;
while (my $foo = $iter->()) {
    push @blah, $foo if ($foo->url =~ /;

for my $baz (@blah) {

I don't know why, but there's some psychological block with Perl that makes me use meaningless variable names. I don't do that in any other language. Or at least I don't do it that much. Anyway, MTBlacklist does the whole bulk deletion thing a lot better.

# Speaking of SixApart, it's great saying that you can stay with 2.6 for free, but you can't download 2.6 any more, and the license prohibits anyone sending it to each other. If 2.6 remained available, maintenance of the 2.6 branch would probably devolve to the community, who would continue to distribute patches and plugins. As a result, 2.6 would compete directly with the official 3.0.

# Back to comments. One reader recently responded to my Real Names, Please policy thus:

...and when you delete technical comments just because a person chooses NOT to give out their real name. Even if I did give you my real name, you still wouldn't have a clue who I was. I think it's more ethical to give a name everyone knows isn't real than to pretend I'm someone else.

I'm not sure why I'm posting this because you'll delete it anyway.

I responded thus:

While I discourage anonymous posting, it's actually quite unusual for me to delete a comment if the only thing going against it is anonymity. I can't remember ever having deleted an anonymous comment that was both on-topic and intelligently written.

If you take the time to read the RealNamesPlease page, you'll see that I merely encourage people "as a courtesy" to provide their real names, and "reserve the right to treat anonymous comments with contempt".

That said, I may have deleted such a comment of yours in the past and just not remember, in which case I don't apologise: this is my personal website, and thus subject entirely to my mercurial whim.

Other weblogs have written comment policies. Back when I wrote “Real Names, Please”, I thought that perhaps I should have one too. The problem with policies, though, is that the moment you write one down, you are limiting your ability to exercise your own judgement.

In any community with a moderation policy, the first (and constantly repeating thereafter) complaint is hypocrisy: that comment was just as ‘against the rules’ as mine, why wasn't that deleted? To which the one and only response is: “because I felt one was worthy of remaining, and the other was not.”

In a society, rules are important, as leaving matters up to the whim and preference of the powers that be leads to injustice. On a personal website, the whim and preference of the powers that be is paramount. I will delete comments that I feel deserve deletion. The only way to predict such things is to better know me.

The reason ‘Real Names, Please’ is stated explicitly is because it's more an attempt to influence behaviour than a moderation policy. The reason is stated quite clearly in the linked page. Real names encourage people to take a personal responsibility for their words. While I may not know who you are, someone does, and the psychological effect of tying the words to your real identity remains.

Pseudonyms are an Internet norm that I wish to discourage in my own back garden. The threat to ‘treat with contempt’ rather than to delete is thus deliberately chosen.

Lazy and Stupid

  • 9:00 AM

It has been calculated that if everyone in the united states did not purchase a drop of gasoline for one day and all at the same time, the oil companies would choke on their stockpiles. at the same time it would hit the entire industry with a net loss of over 4.6 billion dollars which affects the bottom lines of the oil companies therefore may 19th has been formally declared "stick it to them day" and the people of this nation should not buy a single drop of gasoline that day.

So goes this week's annoying email forward (although I had the courtesy to convert it from its original all-caps ugliness).

The stupidity of the whole exercise staggers me. That anyone could believe that a day of not buying gasoline would have even the slightest effect on the oil producers' bottom lines is a sad indictment on people's willingness to ignore inconvenient facts. The inability to perform simple mathematics ($4.6 billion being $16 for every man, woman and child in America, each of whom may or may not own a car, with each car being filled up once or twice a week) is equally depressing.

Then factor in things like the amount of oil that goes to other things (like, say, electricity production). Then figure that everyone will just fill up their slightly-more-empty-than-usual gas tanks on the 20th, having performed their patriotic duty the day before.

The email campaign is, in essence, the answer to the question: "What's the smallest and least effective thing we can do, and yet still feel we're sticking it to those damn A-rabs?" Legislating for more fuel-efficient cars? Too difficult. Removing the insane tax-breaks that make SUVs so cheap and common on the USA? Too difficult. Increasing the quality of public transport? Just too hard. Find ways to reduce personal electrical consumption? No way! We might have to do without!. Promoting research into- and the use of alternative fuel sources? Way too difficult!

Let's just forward stupid emails instead. That'll make us feel better. Yeah.

The debate between static and dynamic typing is a long one, and not one I have a definite opinion on. I tend to jump from one side to the other depending on the phase of the moon. I am going, however, to make a statement now that is entirely true:

Java's implementation of static typing is stupid.

Before anyone jumps down my throat, and because "stupid" is also a general-purpose perjorative, I'm going to give a more formal definition of what it is to be a stupid type system:

A stupid type system is one where the programmer is forced to do unnecessary work for the compiler.

A good way to get an idea of how stupid Java's type system is, is to use a modern Java IDE for a while. Start using IDEA's intention actions, and see just how often IDEA knows what the type of an object is going to be before you bother to assign it a type, or make a cast. Every time you ask the IDE to assign a cast, create a field or iterate over a collection and you select the default value, you're telling the compiler something that IDEA was smart enough to know already.

And with 1.5 and the introduction of generics, the type system is getting even stupider, giving you more and more places where you have to tell the compiler what types to expect because it's too stupid to work it out for itself. Even though the IDEs are smart enough to do this, it's still annoying and disruptive for the programmer to have to make the context switch and alt-enter a cast into place. I'd much prefer Java itself was better able to this sort of stuff itself.

I'd love to see Java have some form of type inference. Because of the way Java treats separate classes as independent compilation units, you'd have to keep interactions between classes manifestly typed. But within a class, there's no excuse for the compiler not to be able to infer the type of variables and method signatures from the objects that are assigned to them, and the methods that are called on them.

You wouldn't lose any type-safety. We are not removing static typing, we're just leaving it to the compiler to fill in the obvious bits. The compiler would still be perfectly able to spot the assignment of incompatible classes to a variable, or the calling of non-existent methods on an object. It could even detect when you were moving incompatible objects in and out of a collection without any tedious mucking around with expressly declared generics.1

The only ambiguity would come from methods that are overridden with arguments of overlapping types, which is really bad practice anyway.

All you'd lose is, well, a lot of wasted typing.

See also:

(This post originally came with a code example which I wrote while also trying to wrestle with CruiseControl. As a result, I quickly removed the example because it was woefully incorrect in almost every respect, and I've already wasted enough time today writing this post. On the other hand, I fixed the CruiseControl build by changing the max size of the permanent generation. Hooray.)

1You'd still need generics so that you'd know you expect the same objects out of a collection as you put in, but they'd be a lot less obtrusive.

Personality Test

  • 10:23 PM

I can't remember on which site I encountered this, but it amused me enough to save a screenshot. At first it looks like an advertisement, but I'm convinced it's really a very sneaky personality test:

Unfortunately, this is a visual gag, and explaining the joke in alt text wouldn't be particularly funny.

Addendum: The amazing thing about this blog entry is that when I look at it, I can feel my unconscious "ad-filter" trying to ignore the image. My brain is doing its best to disconnect the image from the context of the page.

Well, I woke up this morning to find that in the hour and a half before getting up I'd received 558 comment-spams, and they were still coming in from multiple IP addresses.

chmod 000 mt-comments.cgi

Having disabled comments, I then start the long process of deleting 558 spams from 36 different posts.

Each spam advertised some form of perversion that I would much rather not encounter on a Saturday morning

I know, I should be running the latest version of MT2.6 with comment-throttling turned on. I looked into this a while back, It seemed you had to do an awful lot of work1 to get everything working effectively, even significantly more effort than it took to mechanically delete all that spam over breakfast.

What I want is new blogging software. I've wanted it for a while because Moveable type has started to annoy me. To fix the annoyances would involve writing Perl, which always makes me feel dirty2. Now that MT2.6 is a dead-end, and MT3.0 will want to charge me for silly things like adding authors to my Quicklinks blog, the switch seems inevitable.

I shudder at the time I have to invest in moving away from MT. I don't like fiddling around with installation and configuration at the best of times. If I switch, then before I can hack in any improvements, I'm going to have to spend however long it takes getting a new piece of blogging software to get to the state where it does exactly what this one does already: a massive investment of effort to stand in one spot.

Also, I'm way too picky.

  • I don't want to switch to another Perl platform. Perl is icky2.
  • I don't want to switch to PHP. PHP is truly icky2.
  • I can't really spare the server resources for a Java appserver.
  • I don't want to switch to anything that won't let me keep my permalink URLS exactly as they are (no more redirects thankyou, I still have to maintain all the annoying redirects from when I last moved my blog).

Hello Inertia, my old friend.

1 Hopefully, Shelley won't get too worried when a Google search for "Burningbird throttling" shows up in her referrer logs.
2 This is my opinion. You're welcome to your own, differing opinion so long as you don't feel that your opinion invalidates my right to have one.

They should have "Straight Eye for the Straight Guy"

"Hey, mate. Want a beer?"
"You see what Barry was wearing?"
"No, mate. Didn't notice."
"Nice fridge."

I'm resuming my battle against mock objects today. It's not that I have anything against mock objects themselves: they're a really useful testing technique. It just seems they're something that is easy to use badly if you don't pay attention.

There are essentially two uses of mock objects:

  1. To set up a fake environment in which the object you are testing can live
  2. To test what changes the object being tested makes to that environment

Thus, if I'm testing my EditUserDetailsAction I'm going to mock up enough of the model that it can retrieve users (type 1), and I'm also going to test that after the edit is complete, the correctly modified user is sent back to be persisted (type 2).

If you're programming with Mocks you should always keep in mind which of the two you are doing in any case. Confusing them leads to tests that are either brittle or worthless.

The Java mock objects framework that we use here has two sets of methods for "priming" your mock:

  1. the matchAndReturn methods tell the mock object that it may (or may not) receive any number of calls to this method with these arguments, but if it does, return this value.
  2. the corresponding expectAndReturn methods tell the mock object that it will definitely receive a call to this method with these arguments precisely once. You can use the verify method later to ensure that all expected methods have been called.

Two uses for mock objects, two families of priming methods. I doubt I need to draw this any clearer, but I will.

If you're mocking out a method that is just a 'getter' with no side-effects, use matchAndReturn. Otherwise, you end up with annoyingly brittle tests that will fail if the code being tested, for example, asks for a value twice instead of once, or gets the same value through a different code-path1. So long as you get the right value back, your test shouldn't care how it's being retrieved, or how many times2.

If you're mocking out a method that has side-effects, then obviously the side-effect is relevant to your test - you need to ensure that the method is (or isn't) called, and that it's not called more than once (unless it's idempotent, but that's harder to cater for). Thus, for testing that your object is making a particular change to the outside world, you'll have to use expectAndReturn, and verify your mock at the end of the test.

1 Mock object tests will inevitably be brittle in regard to changing implementations, but you can mitigate the problem by setting up a reasonably complete default mock environment for your tests.
2 Obviously, if retrieving the value is expensive, you care. But it's not the place of the unit test to care about how efficient a certain method is.

I have this rule that memes and song lyrics are only posted to my livejournal so as not to annoy the general public. However, since this is both a meme and song lyrics, the double-negative cancels itself out. Or something.

Anyway, the task is to pick one line each out of the next twenty songs from your mp3 library on random play. All songs are in order, although I skipped a few that either had no lyrics, or were by bands that had already appeared.

26 lines from 20 songs

Keep your mouth closed fade and die.
    Take control of your life and survive.
Scarred—your back was turned, curled like an embryo
Awake to the sound as they peel apart the skin.

Love, let me sleep tonight on your couch and remember the
     smell of the fabric of your simple city dress.
I've got my spine, got my Orange Crush.
And when I melt, I can go anywhere: slip under the door unawares.
And she's so smart and independent, I don't think she needs me.

A denial.

And school's out early and soon we'll be learning,
     and the lesson today is how to die.
I'll stand in front of you, take the force of the blow.
I don't pretend to know what you want, but I offer love.
Sign says "Honeymoon to rent". Cloudland into dreamland turns.
...and put a hole in her body where no hole should be.

It's a reefer, do you want some, policeman?
     Or would you prefer me to shove it up your arse?

She could talk to squirrels.
But she'll be walking your streets in the clothes
     that she went out and chose for herself.

Shiva opens her arms now to make sure I don't get too far.
And in the middle of negotiations, you break down.
But don't despair, this day will be their damndest day,
     if you take these things from me.
All you know about me is what I've sold you, dumbfuck.

It all started with Sam Pullara claiming that:

  1. Java method calls and field accesses are faster than their Objective-C counterparts, therefore
  2. Apple should replace Objective-C with Java as the primary development platform on OS X.

Note, that's all the benchmark really tests: the "string comparisons" devolve down to identity equality in both cases. Also note that the "straight C vs Java" comparison later in the article is ridiculously biased: it's comparing an identity check on Java's side with a full string comparison on C's side1, and C still wins on my machine2. (I wrote my own strcmp that does an identity check first. With that, the C version suddenly wins over Java by a factor of ten2).

All of which means precisely nothing. The benchmark bears about as much relation to what really happens in a Cocoa program as, well, some really great analogy that I can't think of right now because it's too early in the morning. Micro-benchmarks are always so ridiculously contrived that they only serve to throw around confusion and mindless advocacy3.

Apple won't switch to Java as the primary development platform for OS X. They can't without rewriting most of the OS. Calling for them to do so on the basis of a benchmark that doesn't even prove what it sets out to prove is just silly.

Addendum: The next version of OS X is going to be called Tiger. Oh how wonderful. Now I'm going to be stuck asking things like "So, will Tiger be able to run Tiger?"

1 One of Java's smart optimisations is that it's actually quite hard to build two identical strings that aren't identical objects, or at least that don't share an identical char[] pointer and offsets. The JVM is quite willing to say "Oooh, that looks like something I've already got in the constant pool. I'll use that one instead."
2 if you compile with -fast -mcpu=G4.
3 If the numbers had been reversed, the entire Java community would be crying FUD.

I went to an Apple seminar (basically an advertisement for WWDC. I wish.) this evening. I'd been to one of these two years ago, and for the most part this one just repeated the same lines as the last: "We're all about open standards. OS X is way cool. We like Open Source. Cocoa is way cool." This one was, however, lacking the disgruntled OpenDoc programmer in the audience looking to take Apple to task for its habit of abandoning technology that isn't quite working out for it.

Two things were interesting this year, though.

The first was the showcase of the profiling tools that come with OS X 10.3. The guy whose name I've sadly forgotten gave an impressive demo of Shark, the profiling tool. I suspect a certain amount of configuration happened behind the scenes, but essentially the demo consisted of:

  • Start Shark
  • Run application
  • Stop Shark
  • Look at statistics

While running, Shark would use instrumentation built into the OS and the hardware to profile all the running applications. After stopping Shark, you get an overview of which applications were taking up the bulk of the CPU time during the run. Drilling down to individual applications, you got:

  • An overview of which functions were using the most time
  • For those functions were source is available, a source listing colour coded by which lines of code were particular "hotspots"
  • Annotations on both of the above views providing clues as to why they might be slow
  • Suggestions on what might solve the problem (using an alternative function, unrolling loops, etc)

It's hard to impart just how impressive the demo was to someone who can only associate profiling tools with the phrase "wrestling with". It was the code-view that surprised me. The simple double-click down to something that the programmer can really identify with.

Of course, the demo was carefully staged so that the application in question was doing something time-intensive that could be made significantly faster by using a more efficient sqrt() routine or enabling Altivec extensions. However, the fact remains that this tool comes included with the OS, whereas every similar tool I've seen for Java is either (a) clumsy, slow and annoying, (b) expensive or most frequently © both.

Keep in mind this thing was profiling C code. Java runs in this carefully managed environment, surely we should have better tools? I suspect that if the Java vendors don't wake up, this is somewhere .NET can really clean up by making similar tools just come with the environment.

The other cool thing that was demo'd was Xgrid, the OS X grid computing framework. In typical Apple fashion, they took a complicated subject (grid computing), and reduced it down to "Here's ten lines of code. I compile it like this, then I tell the GUI to run it across whatever other machines it can find over Rendezvous." And it Just Worked.

Via Ned Batchelder, I learn that Google is seeking to raise $2,718,281,828 in their IPO, which just happens to be a billion times the mathematical constant e. (The integer value, anyway)

Nice to see Google isn't losing its personality, even in the face of gigantic sums of money. "Google. Your irrational investment".

Update: Just over two years ago, I wrote this:

cringer is watching They Live. If I had more money than I knew what to do with, I'd buy a billboard in the middle of Sydney, and just put "OBEY" on it in big black letters.

Addendum: After posting this, I realised that this is probably one of the reasons I don't have more money than I know what to do with.

This makes me jealous of Google. They have enough money to buy the billboard, and if they felt like it, they probably would. Except they wouldn't want to, because they're not evil.