December 2002

« November 2002 | Main Index | Archives | January 2003 »

31
Dec

One of the things I used to dislike most about the Mac was the way that applications stuck around even when you'd closed all their windows. “How annoying” I'd think, as I searched through the Application Switcher to find all the programs I'd started that were still taking up precious resources because I'd never explicitly quit them.

Today, I closed the Evolution window on my Linux box at work. “How annoying”, I thought, as the application cheerily told me it was quitting. “I never asked it to do that!”

I guess that's a pretty strong sign that while I still use three different operating systems regularly, my brain has switched.

Most popular search terms bringing people to The Fishbowl
  October November December
1 janie porche (199) janie porche (60) picking locks (111)
2 janie porche naked (55) i'm looking at gay porn (23) janie porche (103)
3 lego escher (43) lego escher (21) i'm looking at gay porn (51)
4 mixerman diaries (11) janie porche naked (18) mixerman (37)
5 mixerman (10) livejournal hack (16)1 http get (32)

1 If “livejournal hack” and “hack livejournal” were counted as the same query, it would have 31 hits this month, taking it to the number 2 position. There were also five occurrences of “how to hack livejournal”

Similarly, in December, neither made it into the top five, but counted together would have totalled 38 requests, putting it in at number 4.

A co-worker, trying to be polite, and avoid a long rant:

Perl... has some things in common with Visual Basic

Because...

  • 12:32 AM

It's official. The Beatles' Abbey Road is the best LP ever produced.

Something captures George at his most magnificent. Maxwell's Silver Hammer harnesses Paul's twee-ness into something greater. Come Together and I Want You (She's So Heavy) show John in his raw, blistering majesty. Even Octopus's Garden grasps of Ringo's silliness as a musical counterpoint.

And then side two... The whimsical Because... Because, where John takes Moonlight Sonata, plays it backwards, and transports us to another plane. And the whole medley from You Never Give Me Your Money right up to The End. snippets of brilliiance woven into a tapestry that none have ever since matched. Even Polythene Pam, the weakest song on the album, can be credited as the ideal bridge into She Came In Through the Bathroom Window, which segues so perfectly into the sublime Golden Slumbers.

Excellence. I feel privileged to be able to listen to it.

Some disorganised thoughts with no conclusion...

TCP implementations will follow a general principle of robustness: be conservative in what you do, be liberal in what you accept from othersRFC 793, section 2.10

You can't go ten feet on the Internet without having Jon Postel's Robustness Principle quoted at you. As a maxim of protocol design, it's not a bad one. If you write your software in such a way that it always generates correct output, you maximise the number of other implementations that can read what you say. If you also do your best to accept input that does not strictly follow the standards, you maximise the number of implementations that can talk to you.

Like most accepted wisdom, it doesn't quite bear close inspection. The problem arises because following the robustness principle does not protect you from people who do not follow it. The results can be quite chaotic.

Counter-intuitively, Postel's robustness principle ("be conservative in what you send, liberal in what you accept") often leads to deployment problems. Why? When a new implementation is initially fielded, it is likely that it will encounter only a subset of existing implementations. If those implementations follow the robustness principle, then errors in the new implementation will likely go undetected. The new implementation then sees some, but not widespread deployment. This process repeats for several new implementations. Eventually, the not-quite-correct implementations run into other implementations that are less liberal than the initial set of implementations. The reader should be able to figure out what happens next. — RFC 3117 S4.5

A classic example of how this form of ‘robustness’ can let you down is the World Wide Web. Web browsers have always followed the robustness principle, doing their best to render bad HTML through a series of guesses as to what the page author may have intended. The problem was, page authors weren't following their side of the robustness bargain, and suddenly we ended up with a Web where browsers had to be guess-for-guess and bug-for-bug compatible with their predecessors.

If you can't make sense of the spec in 10 minutes no one is going to use it so you can safely ignore it. — Dave Winer, Scripting News

Attitudes like this don't help either. Many hackers (in the perjorative sense) will try to make use of a protocol with a ten minute understanding of it. Very few protocols can be really understood in ten minutes, the closest you can get is a step-by-step recipe .(what Winer calls a ‘Busy Developer's Guide’) that leaves out the why and how for a strict set of whats. Such implementations, written without understanding what they are really implementing, take advantage of the robustness principle by approximating the protocol, and hoping that the implementations they are talking to will accept their approximations. Because one side is doing the right thing and trying to accept bad input, some implementors feel they can ignore robustness entirely.

This is a bad direction to take. It can even bog down protocols and prevent them advancing: just look at the hassles introducing XML namespaces to RSS, because a number of implementations never bothered to learn how XML really worked, and just did pattern matching instead.

Postel's Robustness Principle is a two-edged sword: Gresham's Law [“The bad currency drives out the good”] often trumps the Robustness Principle. — BEEP: Building Blocks for Application Protocols

YKYBHTLW...

  • 9:48 AM

You know you've been hacking too long when...

You come up with an idea for a silly Science Fiction/Horror short story, in which the universe implements reference-counting, and as soon as the number of ‘references’ (i.e. connections to other people) you maintain reaches zero, you are visited by The Garbage Collector.

If your weblog has a comments form, it is a very good idea to have some kind of small-print on the form that explains how the submitted comment is going to be munged. It's very difficult to comment effectively when I don't know the following:

  • How do I start a new paragraph?
  • How do I insert a single linebreak?
  • How do I make a hyperlink?
  • What will happen to any HTML, angle brackets or &entities;?

AOL patents IM

  • 4:59 PM

From Diego Doval, (well, actually I first saw it on the Jabber-dev mailing list, but blog-links are neater) I learn that AOL has patented instant messaging, thanks to a 1997 filing by ICQ.

Before you scoff about patenting the obvious, try to remember back to just how revolutionary ICQ was, and how quickly everyone flocked to it. ICQ introduced the idea that presence would work over the Internet, not just on closed-gate BBSs and online services. People flocked to ICQ in their millions, almost from the moment it was released, because at the time there was nothing like it, and nobody was attempting anything like it.

Sure, in retrospect it seems obvious. If it was that obvious, though, why didn't anyone even try it until the late 90's? And there was lots of art beforehand that could be considered inspiration. But I think the patent certainly has merit as being an invention of something novel and non-obvious. Before ICQ, you either had email, or you had IRC, there was nothing in between. After ICQ, every man and his dog was suddenly talking about instant messaging, presence and P2P.

That said, I think this is a prime example of why patents shouldn't apply to a rapidly developing field like the Internet. The law lags so far behind the innovation that by the time the patent is granted, there are several large players fighting over an established market, and the people who had the idea have already cashed out and sold their stake to a monolith who had nothing to do with the innovation itself. The patent, intended to be an incentive that stimulates advance, become a bludgeon by which it is crushed.

We need a better system. More on that anon, perhaps.

Luckily, IMHO, this patent is unlikely to ever be enforced. Of the other players in the IM game, Yahoo! probably isn't worth suing, Jabber certainly isn't, IBM will just look through its filing cabinet and say “Oh, we noticed you're violating about fifty of our patents just by breathing, I don't suppose you want to do a swap?” and Microsoft can afford to throw enough money at lawyers that they can prove the patent doesn't apply to them. At worst, AOL will just hold the patent up its sleeve against the day it needs a favour that costs less than the lawyers required to tie it up in court.

(This is an expansion of a post I made to the extreme-programming mailing list last week, I guess it bears repeating since I can't be bothered writing anything new right now. It was a response to the comment: “I understand how implementation inheritance works in other languages... but so far I don't see if or why VB's lacking it is so bad... I'd like to hear comments on either side... anyone have any?”).

An object's interface (try to forget the way Java has co-opted the term for its own ends) is the set of messages to which it will respond. Thus, interface inheritance is the declaration that one class will respond to the same set of messages as another. This is the cornerstone of polymorphism: two objects that respond to a common set of messages (having a common interface) can be substitued for each other at compile- or run-time, allowing for more dynamic and flexible programming.

Interface inheritance is the most important aspect of inheritance Remember the advice from Design Patterns: “Program to an interface, not an implementation”. Without interface inheritance, a statically-typed language can not implement polymorphism, which would arguably make it not an object-oriented language.

Implementation inheritance, on the other hand, is a convenient shortcut. It's saying “because I'm inheriting the interface of my parent, it's most likely I want to behave in mostly the same way, so I'll respond the same way to these messages unless I'm specifically told otherwise.” Where we want to respond differently, we override the inherited method implementation with our own.

Implementation inheritance is convenient, but it comes with a number of important shortcomings that you have to keep in mind. It is far less flexible than pure interface inheritance, and it often ties you to the details of your superclass's implementation, breaking encapsulation.

A more general problem with inheritance that in most languages, (i.e. those without design-by-contract), an interface implies, but can not enforce a set of contracts that the class is expected to obey. If you inherit an interface, your class is expected to be able to polymorphically substitute for its superclass, so it needs to obey the same contracts as its superclass. A subclass should be a specialisation of the superclass, its behaviour a subset of the superclass's behaviour. If that is not true, you shouldn't be inheriting its interface.

This isn't helped by the mass of Teach Yourself Java books that encourage OO newcomers looking to implement some functionality, to look for a similar class and extend it. You can generally tell a programmer's OO experience by how well they avoid implementation inheritance, favouring instead encapsulation and programming to interfaces. (For a really bad misuse of inheritance in general, have a look at Java's Applet class, which in the name of convenience for newbies, breaks every tenet of good design by forcing the controller class to inherit an enormous part of the view.)

That said, implementation inheritance has its place. It's not essential for OO in the way implementation inheritance is, but it does save a lot of typing (and duplication) in common cases. Consider, for example, the Template Method pattern. (But then consider how you could replace any use of the Template Method pattern with a State or Strategy.)

In most OO languages, implementation and interface are closely intertwingled, and it's hard to explain the difference between the two to newcomers. Sometimes, I think that it was a mistake to join them as closely as has been done. Perhaps instead we should have broken them up completely and gone with class Foo implements Bar behaveslike Baz

Harry Potter and the Chamber of Secrets
Pedestrian Enid Blyton story with wizards, but little magic.
Bowling for Columbine
It's a shame the people who really should see this movie, won't.
James Bond: Die Another Day
Great mindless action movie almost spoiled by one bogus special-effects sequence.

Everybody seems to have glowing praise of Maven at the moment. The problem is, it's not immediately apparent from the site's front page what Maven actually does. On one hand, I really don't have the time to play around with Maven until I grok it. On the other hand, if I did grok it, perhaps it would save me an inordinate amount of time in the future? I don't know.

What's the pay-off? What's in it for me? Please answer in under one hundred words, with buzzword count below five. A back-of-the-barmat summary would be really helpful, could anyone out there in blog-land either mail me one or post one so I can hunt you down via referers?

Carlos, Why Hibernate is Better Than OJB, For Now:

How and why did this come about? My guess is that Hibernate's goal is "Build the best OR-mapping tool in the planet". OJB's goal however is more like "Build the best ODMG/JDO tool in the planet".

From the Hibernate Q&A

But what really makes Hibernate so good? It wasn't designed by a committee. Hibernate grew out of experience in an actual software project. It doesn't try to be all things to all geeks and so succeeds in doing one thing well.

Hibernate was brought up to 1.0 in a very short space of time, by two programmers working with one of the most efficient motivations a programmer can have: frustration. If any of you have ever done any significant work with Entity EJBs in Websphere 3.5, you'll know exactly the frustration of which I speak.

They weren't trying to produce a general purpose tool, they were trying to solve a problem. In my opinion, that is where all the best tools come from, because the tool never becomes an end in itself, the tool is always the means to some other end, in this case the efficient management of O/R persistence.

There have been calls from some quarters for a fully fledged macro system in Java. I think the chance of this escaping academic study and getting into mainstream Java is somewhere close to zero.

One of the design goals of Java, like it or not, was to avoid dangerous or confusing features. Macros are, by definition, dangerous and confusing. They change the way the language works, in such a way that it becomes impossible to look at a piece of code and guess what it does. They're difficult to write correctly, and difficult to use safely.

I'm not saying I disapprove of macros. I don't disapprove of pointers either. I even believe that goto has its place in the world. But none of these things have a place in Java, because they run counter to the design goals of the language.

SOAPy Madness

  • 6:58 PM

Question 153 of the Undernet #java FAQ reads:

Can I make an IRC chat client with SOAP?

Hmm. It's possible, but everything's possible. It's completely implausible. SOAP manages to maintain state through sessions, but the concept of long-running transactions like an IRC client would require is... sickening.

I've only ever written two SOAP applications. The first was “Hello World”, except it would give back a random quote from the fortune file instead of the boring Hello.

The second was truly diabolical. It was a tunneling proxy. It tunneled TCP/IP. Any TCP/IP whatsoever. Over SOAP.

Hey, I was bored.

Anyway, I tested this proxy by connecting my IRC client to it. It worked perfectly, albeit rather choppily, as the stream was being broken up into lots of little XML documents, turned into HTTP requests and then being reconstituted at the other end of the tunnel.

And yes, it was sickening, but in a compelling, car-crash kind of way.

JSR 201 analysis

  • 10:14 PM

Well, a few hours after writing about JSR-201, I thought I might expand on what I think about the features being proposed.

Enums

Good. The proposal basically creates a shorthand syntax for the Typesafe Enum pattern in Joshua Bloch's Effective Java, and allows you to use these enums directly inside switch statements.

I had a short discussion about this over the phone with a colleague, who was of the enduring opinion that switch statements are a Code Smell, and their use shouldn't be encouraged. I believe that switch still has its place: the choice between switching on the enumeration, and adding polymorphic behaviour to the enumerated type itself, really depends on proximity, and whether the enumerated type should know about the code being put inside it.

One point. Have the compiler issue a warning if you're doing a switch on an enum, and missed one of the possible enumerations.

Static import

Static import adds a behaviour to the import statement, allowing you to import the static methods and fields of a class. So if you statically import java.lang.Math, then you can call abs() instead of Math.abs(). The main target of this feature seems to be the annoyingly bad habit of some developers to import a pile of constants by implementing the interface that defines them.

This is nice syntactic sugar, but otherwise a pretty minor feature.

Auto-boxing/unboxing

This eliminates some of the difficulties inherent in having a distinction between primitive types and Objects. I ranted about this distinction earlier this year. Just to reiterate, I have no problem with there being such a distinction inside the JVM, I just believe it should never have been visible in the Java language itself. To the programmer, it's so much simpler if everything is an object.

Auto-boxing/unboxing seems to me to be a band-aid solution. The distinction still exists, it's just hidden under a layer of (still programmer-visible) conversion rules. Given that the biggest problems with primitives come from the interaction between “primitives aren't objects” and “Arrays aren't really objects either, sort of”, it will be interesting to see just how effectively this problem is made to go away. Will you finally be able to write a single method that can act on any type of array?

Stick a big “wait and see” on this one.

Enhanced for loop

Once again, this goes back to something I wrote about in Java Peeves. Java really needs a convenient, concise way to do closures (or blocks, for Smalltalkers). All we have now are anonymous inner classes, which are far too verbose for regular use, so closures are only ever used in Java when there is no possible alternative.

Foreach takes probably the most common use of Smalltalk blocks, the internal iterator, and creates a syntactic special-case for them. Once again, it's a band-aid solution. Foreach removes the annoying duplicated syntax for the simplest case, but it does nothing to give programmers the chance to remove duplication on the more complex cases. For example, here's an implementation of map over an array, using the three different syntaxes. Assume we have an array of ints, orig[], and we want to increment each value inside it.

Current Java:

int[] dest = new int[orig.length];
for (int i = 0; i < dest.length; i++) {
    dest[i] = orig[i] + 1;
}

With enhanced for, it's even clumsier:

int[] dest = new int[orig.length];
int count = 0;
for (int i : orig) {
    dest[count] = i;
    count++;
}

With blocks, we could just have an Arrays.map() function:

int[] dest = Arrays.map(orig, { int i : i + 1; });

Of course, the map() function would contain the same code as the first example, but the point would be you'd only ever have to write it once, ever. Blocks are a wonderful way to get rid of all sorts of code duplication that pops up all over the place in Java code.

I think my biggest problem with the enhanced for statement is that it's the one thing in JSR-201 that is a step away from the right thing, because it happens to be the most convenient way to match a piece of C# functionality. Once foreach is implemented, the precedent has been set: whenever the lack of blocks causes us to lag behind C#, don't fix the underlying problem, work around it with a variant on what we have already. That leaves me a little cold.

All in all, I'd love to see three quarters of JSR-201 implemented in Tiger.

I found this on WardsWiki, it's an XP Mailing List post by Kent Beck, that gives a pretty good insight into where the ideal of code reuse meets reality:

Although Money seems to be a perfect candidate for the Reuse Grail, it does not work out that way. Therefore, I carry around in my head a pattern language for creating Money and I reimplement it every time from scratch. It takes me about a day, integrated over a month, and the result is exactly what my clients need, and not a penny more.

Cedric tries to introduce some moderation to the coding conventions debate:

But I have to say I am quite shocked by the vociferousness of everyone who has commented on these issues. Come on, guys, we are all professionals. There is no place for hating a bunch of letters or swearing over the way someone writes code. And I believe it is equally inappropriate to be extreme in any of your opinions. The Hungarian notation is neither totally evil nor absolutely perfect. Nor is anything else in our field.

The natural mode of any disagreement on the Internet is highly charged rhetoric. It's because we have this invisible audience that may or may not exist, so the instinct is to play to the crowd. This tends to elevate the most trivial discussion into a flamewar of epic proportions, especially with things that are matters of taste that can never be decided through reason (emacs vs vi, Java vs .NET, or code conventions)

More energy has been expended debating the correct positioning of braces than in deciding whether or not to invade Iraq.

December 3rd

  • 5:51 AM

Happy birthday to me
Happy birthday to me
Three years 'til I'm 30
Fuck fuck fuck fuck fuck fuck.

(Update) Ack! I somehow lost the attribution when I posted this. The quotes are from Russell Beattie:

I need to say that first, both Cedric and Charles made comments like "the IDE will save us" in their posts and IMHO they're both wacky on this point. Languages and any notations you decide to use need to be able to stand on their own. If you're doing something that needs an IDE to figure out, then you're in trouble. Whatever convention you use has to be inately understandable by any programmer walking into your code even using VI.

You don't design things with big wing-nuts just because some mechanic somewhere might have a religious hatred of screwdrivers. Whatever James Gosling might say about IDEs, I have little sympathy for people who think that a text-editor alone qualifies as a complete programming environment.

Things like code-completion, fast class-navigation and Javadoc access, context-aware searches (find implementors, find callers) and inline error detection not luxuries any more. They are essential to efficient programming. And if someone is deliberately choosing to program in an environment that doesn't have them, that someone is either so good they don't need additional notation, or (more likely) wasting time and money.

Interfaces are handy, dandy and cool, but they're there to help structure your classes and allow interoperation without multiple inheritance, NOT to be the prime way of programming. If you're thinking "I'll just program to interfaces and forget about those classes", you need to come up to speed because I think that fad went out a couple years ago.

I don't really follow that either. There are very clear benefits in Java to modelling subsystem and component facades as interfaces, including the ability to transparently separate components using dynamic proxies, or to test them in isolation using mock objects.

I remained silent on the prefix all your member variables with m_ thing, because it's a matter of taste. I find it ugly and mostly useless, other people think it's important, but because it doesn't affect anything outside the class, it's largely irrelevant.

I must, however, disagree with prefix your Interface names with I (e.g. IWindowListener).

The standard argument against such a practice is, again, that it breaks encapsulation: "I am dealing with a type, I don't care if it's an interface or a concrete type."

Well, you should, because they are not equivalent. For example, you cannot "new" an interface, and it's the kind of information I would like to have right off the bat, not when I do my first attempt at compiling and realize that now, I need to find a way to find a concrete implementation of the said interface.

Firstly, I don't know about you, but I never have to wait until compilation time before I discover I can't instantiate an object. Why not? Because there aren't any classes called WorkspaceWithAConstructorThatTakesAString. If I find a class, any class I don't know how to instantiate, I have to either open its definition in my IDE, or read the Javadoc. The point is already moot, the extra I wouldn't save me any time as I would still have to be browsing its documentation to find the list of implementors.

Secondly, an object is only ever instantiated once, but can be used many times after that. This is especially true of Interfaces, which are generally instantiated in one place that knows all about their interface-ness, and then passed around anonymously to lots of other places that don't have to know (think of Listeners, States/Strategies, Comparators).

If you follow the IFoo convention, and you want to change a class into an Interface, you have to change all the places it is instantiated and all the places it is used (in method arguments and declarations). If you don't follow the IFoo convention, you just have to change the instantiations.

(Update) Cedric points out that if you have a good modern IDE with refactoring support, this isn't really a major issue. Considering my argument revolves around the capabilities of IDEs, I guess I'll have to concede that point. :)

Thirdly, and this is my problem with Hungarian notation in general, it's hard to read. Our eyes don't read words letter by letter, we read by pattern-matching the shapes of words, we only fall back on letter-by-letter in the worst case of not knowing a word at all. IApplication takes longer to read than Application. The extra I at the start changes the shape of the word, and your brain takes longer to parse it.

I prefer to have code that is easy to read in the general case, and tools that will tell me the supporting information if and when I need it. Hungarian notation is an artifact of a time when the tools weren't good enough to give us this information in any way but by throwing it all in our face at once. Now we have colour-coding, tool-tips and one-keypress navigation available to us, Hungarian notation is a horrendously clumsy anachronism. The information should be available, but not obscuring the code. Which is why I don't use Hungarian notation, but I do use a good, modern IDE.