July 2002

« June 2002 | Main Index | Archives | August 2002 »

30
Jul

XML-RPC e-mail. Would the developers of the world have any interest in using a XML-RPC based API to send and receive e-mails? XML-RPC email would be nifty, but SOAP email would rock. Using Glue and James this would take a weekend to build. 'course IMHO a bigger problem is that there are no clients for it [rebelutionary]

Whenever I see something like this, I apply the "problem" test. What problem does this solve?

We already have three widely implemented protocols for dealing with mail, one for mail-transfer (SMTP), one for remote mailbox access (POP3), and one for distributed mailboxes (IMAP). The protocols are ubiquitous. POP3 is so simple you can write a basic POP client in under an hour (I did that once to check my mail from work). If you want security, you can tunnel them over SSL (And most clients support that, too)

While none of the protocols are perfect, there is nothing inherently better about XML-RPC as a platform that would improve them in ways that enhancing the existing protocols in a backwards-compatible manner wouldn't do better. At the same time, XML-RPC would complicate the wire protocol (the ability to do a POP3 or SMTP request by typing in a telnet session is a god-send sometimes), while adding the additional complexity of XML-RPC's inherent statelessness. Aside from buzzword-compliance, what problem would be solved through the use of XML-RPC?

For any Java nerds out there, I posted a list of five books a Java programmer should read to my nerd blog.

Two pet peeves.

  1. "4am in the morning". As opposed to what, 4am in the afternoon? I'm quite happy with "PIN number", "ATM Machine" grates slightly, but for some reason, "AM in the morning" is the equivalent of nails on a blackboard. Amy committed this one regularly, so it's probably good that things never worked out for us - she'd have slowly sent me mad, too.
  2. TV advertisements that have modem noises in them. It's turned into the signifier of "Internet" in your advert to have the sound of a modem handshake in the background. My modem is right next to the TV, so I keep thinking the damn thing is redialling when it isn't.

Five books I think you should read if you hack Java:

  • Design Patterns, Gamma, Helm, Johnson, Vlissides. (the Gang of Four).

    There are four stages of pattern-awareness. Ignorance (What is a pattern?), Denial (Oh, patterns are stupid), Over-enthusiasm (Let's use Singleton here! And Visitor here!), and finally enlightenment (That looks like an Adapter... Hmm...) Reach stage four.

  • Refactoring, Fowler

    Keep your code beautiful. An amazingly clear book, very easy to read, with good examples and sage advice.

  • The Pragmatic Programmer Hunt and Thomas.

    An entertaining book. Where I learned about boiled frogs. Some of the advice in this book may seem obvious to you. So why aren't you doing it? Why? Sometimes it takes someone else reminding you what you've always believed to convince you that you've been right all along.

  • Object Oriented Design Heuristics Riel.

    A harder read, far more dry than the last three. But it's the best advice I've read about OOAD yet. Good advice on how to compose your objects, divide responsibilities, and structure inheritance.

  • Effective Java Joshua Bloch.

    The only Java-specific book on the list. If you program Java, you must read this book. Now.

Semantics, in my book, does cover abstraction. There is a trick I use while designing. If I cannot come up with a clear, simple name for a class or method, I probably have a bad design. Confusing names are a sign of a confusing design.Interesting thoughts from Bob. [Hard Werken], quoted in [rebelutionary]

One very useful XP practice (and one of the more difficult) is the adoption of a system metaphor. You model the system you are building on something that is similar in function that already exists. The metaphor helps a great deal with naming things, because you can relate the thing you are building back to the metaphor.

One project we worked on involved receiving data from a number of clients wrapped in some crypto (we had to write the client, too), passing the data on to a third party, and billing the sender. Early in the design stage, we caught on to the idea of having a courier service as our metaphor. Immediately, we had a naming scheme - the crypto became the envelope, the checksum was its seal, the envelope was "weighed" to determine its cost, and then passed to the dispatcher.

Also, the metaphor helped a lot with scoping the project. Once you understand a project in terms of something real and simple to understand (like a courier), you could realise that some features that were on the list would never be used (because nobody would ask their courier to do that), or that some things that weren't on the list were vital.

Of course, coming up with the metaphor in the first place can be really, really tough.

A long-lost verse of Revelations, only recently rediscovered:

And thou shalt know the apocalypse has come, for it shall be writ in words of fire,

Broadcast message from God (pts/1)

The universe is going DOWN to maintenance mode in 5 minutes !!

Ishkur's Guide to Electronic Music is actually pretty nifty.

On the way back from the bank this afternoon, I popped into the bookshop and looked at Bitter Java by Bruce Tate. While the book contains a lot of good advice, there's really nothing more satisfying than looking through a book of Antipatterns and thinking "I already don't do that".

Here's how it works. Brett Morgan asks about a Mozilla-based blogging client, and I point to Mozblog from my nerd blog. A couple of hours later, I happen to notice a link scroll by in my apache logs at www.pastiche.org, pointing to my inset-header CSS trick, which I'm pretty sure I only ever posted to my livejournal, not my nerd blog.

I follow the referrer back, and find that inset header being used (with credit, thankyou!) by Mike Lee, who also linked back to my nerd blog. (in a post dated about an hour before I posted about Mozblog)

Mike runs the Mozblog project. As Eddie the Shipboard Computer would say, "Improbability sum now complete."

Zaphod: Ford, this is Trillian. Hi. Trillian, this is my semi-cousin Ford who shares three of the same mothers as me. Hi. Trillian, is this sort of thing going to happen every time we use the Infinite Improbability Drive?
Trillian: Very Probably
Zaphod: Zaphod Beeblebrox, this is a very large drink. Hi.

Here's how it works. Brett Morgan asks about a Mozilla-based blogging client, and I point to Mozblog. A couple of hours later, I happen to notice a link scroll by in my apache logs at www.pastiche.org, pointing to my inset-header CSS trick, which I'm pretty sure I only ever posted to my livejournal, not this blog.

I follow the referrer back, and find that inset header being used (with credit, thankyou!) by Mike Lee, who also linked back to this blog. (in a post dated about an hour before my post about Mozblog. Mike is, guessing from his link to UWS, in Sydney)

Mike runs the Mozblog project. As Eddie the Shipboard Computer would say, "Improbability sum now complete."

Zaphod: Ford, this is Trillian. Hi. Trillian, this is my semi-cousin Ford who shares three of the same mothers as me. Hi. Trillian, is this sort of thing going to happen every time we use the Infinite Improbability Drive?
Trillian: Very Probably
Zaphod: Zaphod Beeblebrox, this is a very large drink. Hi.

I'm watching a documentary about vicious attack squirrels. I'm glad I didn't know quite how much danger I was in at the time. :)

Update: Actually, it was about one particular squirrel who had a grudge against humanity and was going around town attacking people. The next story in the doco was about a man who was attacked by a parakeet in Walmart.

Thought of the day. Make a blog ui based on Mozilla's mail/news client. [Brett Morgan's Insanity Weblog]

Like MozBlog?

  1. Write the test first
  2. Never write a test that succeeds the first time
  3. Start with the null case, or something that doesn't work
  4. Don't be afraid of doing something trivial to make the test work
  5. Loose coupling and testability go hand in hand
  6. Use mock objects

Write the test first

This is the Extreme Programming maxim, and my experience is that it works. First you write the test, and enough application code that the test will compile (but no more!). Then you run the test to prove it fails (see point two, below). Then you write just enough code that the test is successful (see point four, below). Then you write another test.

The benefits of this approach come from the way it makes you approach the code you are writing. Every bit of your code becomes goal-oriented. Why am I writing this line of code? I'm writing it so that this test runs. What do I have to do to make the test run? I have to write this line of code. You are always writing something that pushes your program towards being fully functional.

In addition, writing the test first means that you have to decide how to make your code testable before you start coding it. Because you can't write anything before you've got a test to cover it, you don't write any code that isn't testable.

Never write a test that succeeds the first time

After you've written your test, run it immediately. It should fail. The essence of science is falsifiability. Writing a test that works first time proves nothing. It is not the green bar of success that proves your test, it is the process of the red bar turning green. Whenever I write a test that runs correctly the first time, I am suspicious of it. No code works right the first time.

Start with the null case, or something that doesn't work

Where to start is often a stumbling point. When you're thinking of the first test to run on a method, pick something simple and trivial. Is there a circumstance in which the method should return null, or an empty collection, or an empty array? Test that case first. Is your method looking up something in a database? Then test what happens if you look for something that isn't there.

Often, these are the simplest tests to write, and they give you a good starting-point from which to launch into more complex interactions. They get you off the mark.

Don't be afraid of doing something trivial to make the test work

So you've followed the advice in point 3, and written the following test:

public void testFindUsersByEmailNoMatch() {
       assertEquals(
            "nothing returned", 
            0,
            new UserRegistry().findUsersByEmail("not@in.database").length);
}

The obvious, smallest amount of code required to make this test run is:

public User[] findUsersByEmail(String address) {
      return new User[0];
}

The natural reaction to writing code like that just to get the test to run is "But that's cheating!". It's not cheating, because almost always, writing code that looks for a user and sees he isn't there will be a waste of time - it'll be a natural extension of the code you write when you actively start looking for users.

What you're really doing is proving that the test works, by adding the simple code and changing the test from failure to success. Later, when you write testFindUsersByEmailOneMatch and testFindUsersByEmailMultipleMatches, the test will keep an eye on you and make sure that you don't change your behaviour in the trivial cases - make sure you don't suddenly start throwing an exception instead, or return null.

Together, points 3 and 4 combine to provide you with a bedrock of tests that make sure you don't forget the trivial cases when you start dealing with the non-trivial ones.

Loose coupling and testability go hand in hand

When you're testing a method, you want the test to only be testing that method. You don't want things to build up, or you'll be left with a maintenance nightmare. For example, if you have a database-backed application then you have a set of unit tests that make sure your database-access layer works. So you move up a layer and start testing the code that talks to the access layer. You want to be able to control what the database layer is producing. You may want to simulate a database failure.

So it's best to write your application in self-contained, loosely coupled components, and have your tests be able to generate dummy components (see mock objects below) in order to tests the way each component talks to each other. This also allows you to write one part of the application and test it thoroughly, even when other parts that the component you are writing will depend on don't exist.

Divide your application into components. Represent each component to the rest of the application as an interface, and limit the extent of that interface as much as possible. When one component needs to send information to another, consider implementing it as an EventListener-like publish/subscribe relationship. You'll find all these things make testing easier and not-so-coincidentally lead to more maintainable code.

Use mock objects

A mock object is an object that pretends to be a particular type, but is really just a sink, recording the methods that have been called on it. One implementation of mock objects I wrote in Java using the java.lang.reflect.Proxy class can be found here, but I'm sure there are more capable implementations elsewhere.

A mock object gives you more power when testing isolated components, because it gives you a clear view of what one component does to another when they interact. You can clearly see that yes, the component you're testing called "removeUser" on the user registry component, and passed in an argument of "cmiller", without ever having to use a real user registry component.

One useful application of mock objects comes when testing session EJBs, without the hassle of going through the EJB container to do it. Here's a test class that checks a session EJB correctly rolls back the containing transaction when something goes wrong. Notice also how I'm passing a factory into the EJB - this is something that happens quite often when you want to be able to alternate implementations between test time and deployment.

import org.pastiche.devilfish.test.*;
import junit.framework.*;
import java.lang.reflect.*;
import javax.ejb.SessionContext;

public class MonkeyPlaceTest extends TestCase {
      private static class FailingMonkeyFactoryHandler 
             implements InvocationHandler {

         public Object invoke(Object proxy, Method method, Object[] args)
             throws Exception {
             if (method.getName().equals("createMonkey")) 
                  throw new MonkeyFailureException("Could not create");
           
             throw new UnsupportedOperationException("Didn't expect that");
         }
      }

      public void testFailedCreate() throws Exception {
         MockObjectBuilder factoryBuilder = MockObjectBuilder.getInstance(
             MonkeyFactory.class,
             new FailingMonkeyFactoryHandler());

         MockObjectBuilder contextBuilder = MockObjectBuilder.getInstance(
             SessionContext.class);
         MonkeyPlaceBean bean = new MonkeyPlaceBean();
         bean.setSessionContext(
             (SessionContext)contextBuilder.getObject());
         try {
             bean.newMonkey(
                (MonkeyFactory)factoryBuilder.getObject(),
                "fred",
                "bananas");
             fail("Expected monkey failure exception");
         } catch (MonkeyFailureException e) {
             assertEquals("session was rolled back",
                 new MethodCall("setRollbackOnly"),
                 contextBuilder.getHandler().getMethodCall(0).getName();
         }
      } 
}

From EFnet #java, discussing why the drop-down picker-thingy is called JComboBox

[Carlton] I've always believed a combo-box is a drop-down picker that you can also type into.
[SamBecket] i always thought of a combo box as a box containing Combo brand snacks
[Carlton] Sam: But if you pay a few bucks extra, you get a bucket of fried chicken.
[SamBecket] Carlton: That would be a bucket o' chicken, a very different UI component
* Carlton nods. But according to the UI guidelines, you should avoid fried chicken in anything but thick-clients.
[Carlton] For a thin client, you'd use Lean Cuisine[tm] instead.

Conversation at work, that will only make sense if you've used Websphere Application Developer or Eclipse:

[David P] Every so often, I just get a GPF and it vanishes.
[Neville] (referring to a big piece of paper from a previous project that we used to tick every time VisualAge crashed) We need another one of those posters with the check-marks.
[David R] Or a dartboard with a picture of WSAD...
[Charles] Yeah, that'd be a good idea. Except every time you threw a dart at it, it'd land in the wrong perspective.

Back to Brett.

I feel the sudden need for a new xml file format that we can put our web pages which details which books are in our libraries, various meta-data, including a rating. Would make getting an instant understanding of the strengths and weeknesses of another geek fairly instantaneous.

(head in clouds mode on) That would be neat. It'd have to be very simple, though. Title, Author, Publisher, ISBN. You could then have a "book aggregator" that monitors blogs of nerds with similar tastes, and notifies you when one of them has read a new book.

[Later...] Being serious for a moment (HAH!), I suspect a problem with trying to write a book just about XUL is the role XUL appears to play in Mozilla. XUL appears to be an xml'ified and application specific .xresources file, with the addition of javascript to make things fun.

I've never done X programming - to me an xresources file was just where I chose what colour things should be, so I can't comment on its similarity with XUL. XUL is to Mozilla as Swing is to Java - it's the whole front-end.

But yes, that's the problem with the book. It shows you how to lay out a GUI, how to style it and make it do things with Javascript, how to write a skin for Mozilla, even how to bind your XUL to an RDF document using XBL. But it's very light on how to use XUL to make Mozilla do interesting things. Which in one way is fair enough - you buy a Swing book to explain Swing, not to tell you how java.io works. But on the other hand, it would be different if there was no book on how java.io works that you could get instead.

According to google, my nerd weblog is the 16th most influential page about naked desktop people

I wrote about my "Java Peeves", Brett Morgan linked to some more issues, so I thought I'd add a few more logs to the fire and point to Jamie Zawinski's "Java Sucks" page, which starts off like this:

I think Java is the best language going today, which is to say, it's the marginally acceptable one among the set of complete bagbiting loser languages that we have to work with out here in the real world. Java is far, far more pleasant to work with than C or C++ or Perl or Tcl/Tk or even Emacs-Lisp. When I first started using Java, it felt like an old friend: like finally I was back using a real object system, before the blights of C (the PDP-11 assembler that thinks it's a language) and C++ (the PDP-11 assembler that thinks it's an object system) took over the world.

...and then proceeds to put the boot in. (Note, the article was written in 1997, so some things like the speed of the virtual machine, and the lack of ability to iterate over Strings and set weak references have been fixed since)

From IRC

[Carlton] CVS is a drug. You start off just trying it in doses, then suddenly you find your entire life is in CVS.
[Carlton] And it's pushy. It keeps asking you to commit.
[Carlton] "But I'm not ready! Can't I just checkout some other projects? We can still update!"

Coming soon: The "Charles Needs a Life" fund.

The problem with that is that some people have already built mental models that include where the data is on why physical device. I have used "dumbed down" systems where things like this were completly hidden, and it led to a feeling of vertigo as I couldn't find where said program was putting my files. Made me want to reach for find. But this was win3.1, not linux. :) [Brett Morgan's Insanity Weblog, "Dumbing down can be dumb"]

I expect you also know what a hard drive looks like, and even what hard drive platters look like. My mother, on the other hand, went through a long period where I would occasionally be called on to "find" all her documents, because Word wasn't opening the Open dialog in the same directory that it used to.

You have a feeling of vertigo because you don't know where your files are going, and you don't trust the program to be able to find them for you if you need them. But the concept of "where your files are" is already an artificial one. You're used to your files being "somewhere" in a directory tree. Do you also worry about which inodes your files are using up, or pay specific attention to how each file is fragmented on the disk?

The heirarchical filesystem will never go away, because it's a very efficient way to sort files, and it's a very convenient organisational model for programmers. Power-users are also used to the filesystem, and would feel lost if it vanished. What needs to be done is more work to shield the user from the confusing things that the programmer and power-user like.

I'd like to see a world where the heirarchical filesystem is like the Unix shell in OS X. If you know what it does, it's a powerful and useful thing to be able to use directly, but if you don't know what it does, you can safely ignore that it even exists.

BeOS made a good start in this direction by adding rich meta-data, and database-like querying to the fs. You didn't have to organise your mp3s into directory by artist and album like I've done on my Windows machine (although I'm sure people did anyway), because you could tell the filesystem to just grab and sort all the mp3s by artist and album.

It's no coincidence that iTunes and iPhoto hide the filesystem, as does every non-Unix email program in existence. The problem is that because the capability to make a better way of finding files is not built into the underlying OS, it is different from application to application, which makes those apps that hide the filesystem harder to use the moment you want to copy data between them, or open a file in an application it wasn't created in.

I am sitting at work, hitting myself over the head with a plastic dinosaur called 'Fluffy'. Fluffy is our release token. You have to be holding him to integrate your code into source-control.

In a previous project, the release token was a big blue plastic head full of {Australia: lollies, UK: sweets, USA: candy}, but I gained several pounds during that project so it probably wasn't too good an idea.

I wanted to get a rubber chicken instead of a dinosaur, but the only place we could find one was in Gowings, and they were asking $AU25 for it. I still think we should have bought it, just for the fun of expensing "$25: Rubber chicken".

I just upgraded to Ximain GNOME Desktop on my office workstation. Cleverly, it spotted all the SMB shares I had mounted in /mnt, and put them all on my desktop as icons. The icons were stylized drawings of HD platters.

The Mac does it little better - the default HD icon on my OS X TiBook was a very nice drawing of a hard drive, another thing that your average user isn't likely to recognise. I know, I've done tech support. 75% of the people I did end-user support for when I worked at Q-Net thought "hard drive" meant "That big off-white box thingy with all the computer stuff in it. Windows 9x represent drives as plastic things that seem to represent external hard drive cases, something that's not exactly been common for PC users since the early 90's.

I spent a while thinking about this, and the reason we can't come up with a good metaphor for drive arrangement that doesn't assume the user knows what a hard drive is, and what one looks like. I then hit myself on the forehead and realised I was thinking the wrong way around.

All our icons for hard drives suck because... the hard drive is not a concept that the UI should be exposing to the user. Until we abstract the filesystem to the point at which it is invisible to the user, and the user just thinks in terms of organising and sorting their various bits and pieces, filesystem programmers and desktop UI designers haven't done their job properly.

I liked this one:

Do you remember the original Batman movie? I think whenever MacWorld is on Bill Gates becomes the Joker. I picture him sitting at home watching the keynote (on Quicktime of course) saying "Where does he get those wonderful toys?" (WAV)

[rebelutionary]

dewhitton posted the list of 100 albums you should remove from your collection immediately.. Out of those 100, I own the following.

(note: the list will not display properly in any browser (such as Mozilla) that parses SGML comments correctly. I had to use Netscape 4. Boo.)

Those albums from the list that I own, still listen to, and won't give up, so nyeah.

  • Nirvana - Nevermind
  • Nine Inch Nails - Pretty Hate Machine
  • White Stripes - White Blood Cells
  • Radiohead - I Might be Wrong
  • Hole - Live Through This
  • Pink Floyd - Dark Side of the Moon
  • The Beatles - Sgt. Pepper's Lonely Heart's Club Band
  • Bob Marley & the Wailers - Legend
  • The Prodigy - Music for the Jilted Generation

Albums I own, don't listen to any more, but still want to keep, so nyeah.

  • R.E.M. - Out of Time
  • Violent Femmes - Violent Femmes

Those albums from the list that I own, but wouldn't mind not owning.

  • Chemical Brothers - Dig Your Own Hole
  • Smashing Pumpkins - Mellon Collie and the Infinite Sadness
  • Offspring - Smash

Java Peeves

  • 10:28 PM
I got annoyed today and wrote about a few Java Peeves.

Compiler optimizations disguised as language features.

The artificial distinction between primitive types and objects is just that. Artificial. It exists in the compiler and JVM because it's more efficient to deal with the number 4 than an Integer object representing the number 4.

This is broken. The programmer should not be responsible for this sort of optimization, it's the responsibility of the compiler.

The same goes for the array. Because the Array isn't a real object, all of the methods needed to manipulate it are static methods of the java.util.Arrays class, except of course for System.arrayCopy(). On top of that, because primitive types are not objects (and thus arrays of primitive types are not arrays of objects), that interface is cluttered with identical methods for every different primitive type!

And I still don't get the mental gymnastics behind String[] foo = (String[])list.toArray(new String[0]); but it works, so I don't touch it.

But, you say, we need the Array to be special because unlike collections, arrays are keyed to a specific type, instead of just storing Object. To this, I reply that this is broken as well:

Object[] bar = new String[3];
bar[0] = new Integer(1);

You need to be able to cast all objectified array types to Object[] to make it possible to write methods that handle all object arrays. Once cast, the compiler won't pick up you putting the wrong kind of object in the array - you'll get a runtime error instead.

The exception heirachy.

Exception and Error are subclasses of Throwable. So far, so good. RuntimeException is a subclass of Exception. This is the wrong way round. 90% of the time, you don't want to catch RuntimeExceptions, but you do want to catch checked exceptions. So the idiom has to be:

try {
      ...
} catch (RuntimeException e) {
      throw e;
} catch (Exception e) {
      do something
}

This wouldn't be so bad if the exception hierachy below Exception had been better designed, but there are far too many places in Java where you have to catch five different exceptions, none of which share a common ancestor higher than Exception, and all of which you want to do exactly the same thing with.

Lack of blocks/closures

Sure, there's nothing you can do with a closure that you can't do with an anonymous inner class, but the overhead required to write an inner class discourages their use, as is shown by the lack of internal iterators in the Collections API. Hence, whereas in Ruby I'd write "list.each { |thing| doSomethingTo(thing) }", in Java I have to write:

for (Iterator i = list.iterator(); i.hasNext();;) {
     doSomethingTo(i.next());
}

I Will...

  • 2:48 PM

During a discussion on IRC about the merits of helping people, I remembered something I wrote years ago on the subject.

I Will...

  • I will help people who are willing to help themselves.
  • I will help people who respond to advice critically, and demonstrate that they understand what was said, and can extrapolate further from it, and possibly teach me something.
  • I will contribute advice to a forum, since that way I get back far more than I give.
  • I will offer my opinions to anyone who is stupid enough to listen.
  • I will help friends, secure in the knowledge that if I don't have time to help, or it's getting annoying, I can just say so, and a friend will be considerate enough to stop asking.
  • I will help anyone who pays me enough. However, I don't do a similar deal for aggravation and personal abuse.
  • I'll aggravate and personally abuse people for free. :)

From an otherwise boring letters page on The Register (although I did learn that C# and Db are actually slightly different frequencies, which I never knew before):

Just to let you know, # is also the abbreviation for fracture in medicine ( can't speak for the US though). For example C-Spine # = fracture of the cervical spine ( a broken neck). So the new M$ product C#, accordingly is either paralysed or dead, says Pete W.

I like this turn of phrase. It appeals to the nerd in me.

The meal “Lunch” has unexpectedly departed, because an error of type SevereStomachBug occurred.

To avoid further problems, you should remove other meals and restart the digestive system.

[mpt]

The Register tells us Windows 2000 has nine months to live. This is a great pity - Win2k is the only decent OS Microsoft have ever produced, and given the user-hostile directions they're going with XP and Palladium, this situation is unlikely to change. So this means my current copy of Win2K is the last Microsoft OS I will ever purchase. That is, unless Palladium turns into a reality and locks us all firmly in the Microsoft trunk for all time, gasping our last breath in Bill Gates' leaky carbon monoxide.

Mike Cannon-Brookes writes an essay on what he calls The Salami Effect, in essence the way small things can add up to be big things if you don't watch out.

In programming, I've seen this concept described in two forms, as the Boiled Frog effect, or as Broken Windows. Often the two are presented together, as they are in Andy Hunt and David Thomas' rather impressive book, The Pragmatic Programmer.

The Boiled Frog analogy comes from the (disputed) theory that if you place a Frog directly in boiling water it will jump out, whereas if you put it in cold water and then slowly raise the temperature, the frog will never notice it's getting too hot until too late. Result, one boiled frog.

The Broken Windows theory comes from an (also disputed) theory of public policy usually used to justify "zero-tolerance" crime policies. The theory is that a single broken window left unfixed in a neighbourhood is an attractant to further vandalism - it gives the impression that nobody cares about the neighbourhood, and thus the area is ripe for bad elements to move in.

What does this mean for programming? Well, it turns out that even though both theories have been discounted in their original forms, they make a lot of sense when coding, especially as part of a large project. Every time you choose to do something in your code that is inelegant, perhaps for the sake of hitting your deadline, the individual effect may be small, and you may be like the boiled frog and not notice how the rot is spreading through the whole codebase.

And likewise, if you leave something bad in your code, a co-worker will see it and say "Well, Charles did it like this, so it must be OK". One broken window becomes many, with the same result.

The solution? To refactor mercilessly. If you see a broken window? Fix it immediately. Keep a careful eye on the temperature of the water, because while it may not seem too hot now, and a few bits of ugly code may help you in the short term, overhauling a rotting code-base is never fun, and usually costs you far more time and effort than you'd have spent getting it right when it was just one cracked window.

While watching the Wimbledon final, I wrote a long-ish essay on why the current state of Instant Messaging is Bad and Wrong.

Instant messaging, as it currently stands on the Internet, makes absolutely no sense. It's a joke, and it's the complete antithesis of what the Internet should be.

Most people get by with one email address. I have several, because nerds seem to collect email addresses in the same way that office drawers fill up with bits of stationary that you never could work out the use of, but I generally get by with just the one. I don't need more than that because I know anyone on the net who can do email, whatever their provider, can send something to that address. Even users of AOL, which has its own internal proprietary protocol for email, can send me a message, because AOL co-operates with the Internet by setting up a gateway between their protocol, and the Internet's protocols.

On the other hand, I have four different IM accounts - one ICQ, one Jabber, one MSN Messenger, and one AOL Instant Messenger. I need all these accounts because most of my old-school net.friends use ICQ, the more recent use AIM, and one of my ex-girlfriends uses MSN-IM. Users of Yahoo messenger can't get in touch with me at all. Users of AIM can not send messages to users of ICQ, despite the fact that they're owned and run by the same company! This means I either have to run four IM clients at once, or try the third-party hybrids that often lose connection to one or other of the IM networks as the network tries to keep off the advertisement-free clients.

This runs so counter to the spirit of the net that it's a real worry. Instant Messaging is the first ubiquitous application added to the Internet since HTTP, and it shows how the world changed overnight while our backs were turned.

Partly, this is because of how IM came about. Nobody went around saying "We need instant messaging", what happened was a company produced ICQ, launched it on the net, and almost overnight, everybody was using it. ICQ took its architecture not from the (open, decentralized) Internet on which it was positioned, but from (closed, centralized) America Online, the company whose internal IM system inspired ICQ's function, and who would eventually, in a strange twist of history, buy ICQ itself.

ICQ launched the model for all popular Instant Messaging systems since. The system was based around a central directory server, a proprietary protocol, and a free client and free service. The client and service must be free, because the value of an IM service is directly proportional to the number of people who use it. If you make any barrier to adoption, your service won't be worth the money you're charging for it.

ICQ and Yahoo Messenger seem to exist on advertising revenue, but the economics of what are now the two leading IM providers is based on how it adds value to an existing service. AIM adds value to AOL because fee-paying AOL users can talk to people outside the previously closed system. AIM is also a vector for advertising AOL, which is why AOL is fanatical about trying to prevent unsanctioned IM clients using its system. MSN Messenger adds value to Windows , or at least allows Microsoft to leverage Windows to steal AOL's thunder (so technically it's not free. Whenever you buy any Microsoft product, you're paying for MSN Messenger, Hotmail, Internet Explorer, Media Player, and all those other add-ons, whether you want to use them or not).

It is remarkable to find a service that seems to be mostly paid for by people who don't use it.

Let's go back to contrasting all this with email. Who pays for email? Well, you may not notice, but you do. Your Internet provider runs a mail-server. By convention, all mail-servers on the Internet freely share mail with each other (spam notwithstanding), so the cost of the system is distributed across the Internet service bills of all its users.

I can not emphasize this enough, but this was the reason the Internet got popular in the first place. The value of the Internet was in the way it allowed all the previously closed systems across the world to talk to each other. There was electronic mail before the Internet, but it was all shut away inside networks using proprietary protocols that couldn't communicate with each other.

If you look at the configuration file of sendmail, still the most popular server software for routing Internet e-mail, you'll find an entire programming language hidden within, designed to facilitate the conversion of mail from internal to public protocols, and back again. As the Internet matured, this became less and less common, to the point that most new mailserver software only speaks the Internet protocol, and doesn't think it may need to talk to BITNET or UUCP.

At the time it was being designed, Internet e-mail had its advantages. It was devised in the very early days of the Internet, when there was time for the engineers to get things done right, rather than done quickly. Also, because of the youth of the Internet, e-mail could poke its way into other protocols - mail-servers find each other using a special "MX" record inside the DNS.

There is, of course, an IM protocol that does things the right way - Jabber. Your identity in Jabber looks suspiciously like an email address, and for good reason. It is a decentralized system, where anyone can run a server (like Internet e-mail the protocol is open for anyone to implement, and there is a Free server any technically savvy administrator can download and install). Jabber servers agree to cooperate with each other. It would not be unfeasable for each ISP to run its own Jabber server in the same way as they all run mail-servers.

The problem is, the only people promoting Jabber are the nerds who created it, and the main Windows Jabber client isn't particularly useable - it confused the hell out of me. So people will continue to use the ubiquitous clients that don't talk to each other, and will usually have to run three or four of them.

What needs to happen, is the same kind of bringing together of disparate systems as happened to make e-mail the killer application of the Internet. Probably using Jabber as the glue, the providers of Instant Messaging need to be joined together by a common protocol, and a way of addressing between systems. I have no idea how this is going to happen, but from the point of view of a consumer, the current system of four different clients is intolerable, and must collapse under its own weight eventually. One possible light is the recent news that the IM client to be built into the next version of Apple's OS X will be based around Jabber, but the idea of Apple playing the peace-maker between Microsoft and AOL made me laugh so hard I almost bust a lung.