While uninstalling some software, my computer asked me to make a choice:

Things to download, because it is the second last day of the month, and I still have two and a quarter gig left:
If you can’t get a hug any other way, here’s something to try:
Your victim new friend will be delivered and ready to cuddle in no time flat.
Further suggestions:
Good luck!
A component’s API is critical to its success. A good component with a bad API is a bad component. It is the users of an API that decide whether it is a good API or a bad API.
A good API is an API that makes my life easy. Four ways that an API can make my life easy are:
1. Simplicity. I want as few classes in the API as is reasonable, with as few methods on each as is reasonable. Small APIs are good—because there is less to learn—but I’d rather have a few extra classes if that makes the API as a whole simpler.
2. Documentation. I want to know what each class and method does. I want to know when and how it fails and what it does if I pass null or some other invalid argument. I also want to know how the component interacts with its environment in response to my calls.
3. What not How. 99% of the time, I don’t care how the internals of a component I am using work. Really, I just don’t. Therefore, the interface should reflect what the component does, not how it does it.
Your report generator component uses XML internally? Fine. But don’t give me an API that looks like an XML parse tree. Especially not if you’re going to mark half the methods “for internal use only”. Sheesh.
4. Compact Usage. The fewer lines of code it takes to make a component do what I want, the better, so long as the resulting code is still understandable. For instance, here is a method I have re-written for nearly every Java project I have worked on:
public static Properties loadProperties(String name)
throws IOException {
InputStream is = getClass()
.getResourceAsStream(name);
Properties p = new Properties();
p.load(inputStream);
return p;
}
Why do I have to write those six lines over and over again? An API designed for compact usage would include an additional factory method on Properties so that I could write:
Properties p = Properties.loadResource(name);
In summary, there are many parallels between building good GUIs and building good APIs. Practice helps, as do writing out use cases and prototyping the interface. In the end it comes down to the same hard truths—some programmers can build good APIs, and some programmers can’t. And every single one of us likes to think that he can.
The other night, I showed my two boys—eight and five—the Fatboy Slim Weapon of Choice video. They are too young to remember the song from its late-2000 release, but it is such a seriously cool video clip that a loving father would not deprive them of the experience.
Connor, my five year old was particularly amazed at the flying sequence and asked, “How does he stay up?”
“He has wires holding him up,” I explained, “You can’t see them because they’re very thin.” Connor thought about it, figured out how it might work and was happy.
The three of us watched the video twice and then I decided to introduce the boys to some Internet culture in the form of a stick figure rendition of the same video. The boys watched, rapt. When it finished, I asked them what they thought. Mitchell nodded, but Connor thought of the stick figure flying through the air, wrinkled his little forehead and asked, “What held that man up? There weren’t any wires.”
Our integration build broke at 9:30 this morning. Here is the error message:
build-internal-web-war:
[javac] Compiling 134 source files to
/home/WebSphere/build_jp/cvs_temp/build_internal_web
[javac] error: The encoding null is not supported
[javac] 1 error
That was it. No line numbers. No file name. Just a hint that something had gone wrong in a compiler input routine, somewhere.
A quick google gave two results. It looks like the problem is specific to the IBM Java compiler on Linux. One of the hits recommended upgrading to 1.4—which we can’t do—while the other was at a bit of a loss, save for rearranging the source until the compiler bug disappeared.
Fortunately, I did know that the system compiled at 8:30, so I went and found the files that had changed. There were ‘only’ 14. I wrote the list in my notepad.
After winding the source tree back to it’s 8:30 state (cvs update -D “8:30”), I went though each file on my list: check out the file as at 9:30, recompile, tick it off the list. The very last file on the list was the problem.
To cut a long story short, the culprits were two non-ASCII characters buried in a comment—0×93 and 0×94. A co-worker had cut and paste the comment and a few other lines from an example on the Sun website. The comment had not caused a problem with the Windows-based IDE compiler, but had b0rked the Linux compiler.
The IBM Linux compiler (version 1.3.1) cannont translate non-ASCII characters to Unicode. This is annoying, but understandable. More annoying, and less understandable is the complete lack of any context to the error message. I hold no hope for getting this fixed.
If there had been better error messages, I could have had the problem fixed in five minutes, instead of two and a half hours.
up at four
out the door
before five
rushing drive
plane at six
check in quick
eat at seven
up in heaven
land at eight
taxi wait
arrive at nine
I feel fine
Inspired by David. Go read his poetry, it’s much, much better than mine.
PS: Let me know if you would like me to send you an email. Then you can tell your grandkids that you once had an electronic conversation with somebody who knew David before he was famous.
Getting ready to dress up a Python module for release, I got to asking myself which __magic__ variable names the module should declare. Some of these are part of the language, while others are defined by convention. There are more than a handful and they don't seem to be documented in one place anywhere on the web, so I made a list for future reference.
Unless otherwise noted, this information is cribbed from the Modules entry of the Language Reference.
__name__import statement.__doc____file____dict____all__from module import * is executed, the public names defined in module are imported. If it exists, the __all__ variable defines the public names, otherwise the public names are all the ones without a leading underscore.__version__ __version__ = "$Revision: 1.18 $". The ever-amazing pydoc module / script / search-engine / webserver processes this variable specially. __date____author____credits____author__ and __credits__ variables starts here.No blogging today. Too busy reading Dragon’s Egg by Robert L. Forward.
“It Should Just Work” is a wonderful computing cliche that I can no longer say with a straight face.
However, after making a check-in this morning, I couldn’t think of a more appropriate phrase to reassure a co-worker that I had fixed the problem. “It will be alright now,” would have been too strong a statement. “I hope it works,” would have been accurate, but did not express my level of confidence correctly.
Can you explain—in plain and simple English—the phrase “should just work”? Try to do it in one sentence or less, and without using the words “should,” “just,” or “work”?
Today I was developing a report that runs against our database. We want the reports to be able to be run from a few different WindowsNT machines, and ODBC looked a reasonable way of providing some location transparency.
“David”: did the obvious thing – went to the Windows Control Panel, clicked on the “Data Sources (ODBC)” icon and set up a data source. I then went to the Control Panel, clicked on the… ?
There was no Data Sources icon on my Control Panel. Nowhere. And so began a few fruitless hours of installing database drivers (DB2, Notus Lotes, and multiple versions of the Microsoft Data Access Components), ratting through the Windows Registry, searching both Google and MSDN, comparing my PC with David’s working one and, at length, inspecting directory listings for likely looking files.
After about two and a quarter hours, I found a whole bunch of “control panel applet” files in the System32 directory. They look like DLLs but have a .cpl extension. The missing “Data Sources (ODBC)” program was cunningly disguising itself as odbccp32.cpl, and I could run it by double clicking it. Woohoo!
That was enough to get me going, but I also wanted to know why the Control Panel applet was hidden. I Googled control panel cpl hidden. Paydirt. The top search result described a registry key named HKEY_CURRENT_USER\Control Panel\don’t load.
Firing up a registry editor, I deleted the odbccp32.cpl value from under the don’t load key, and the “Data Sources (ODBC)” icon magically reappeared in the control panel.
I could speculate on the reasons why such a key might exist, how many other such flippantly named keys might be in the registry, why my user profile was hiding the Data Sources icon (and Network Settings icon too!), or even how I might have tracked down the problem more quickly. But the big take home lesson was supplied by Charles when he suggested:
You really should write to Bill Gates and ask him when he’s going to get around to fixing Windows NT 4.0.
Charles recently blogged on the topic of wonder and technology:
It’s important to maintain that sense of wonder. The net is a pretty amazing thing, held together by a bunch of people who are probably massively unappreciated in their attention to the plumbing.
This must have been resonating around the back of my brain, because it leapt to mind when Mitchell—my eight year old—reminded me of another sense of wonder, a kind of wonder all boys know at age eight . He said:
I wonder what this custard tastes like with honey-barbeque sauce in it.
And like Charles, I also conclude that it’s important to maintain that sense of wonder.
Hans Nowak and Richard Jones both had a few bones to pick with a previous post, Things That Annoy Me About Python, and left comments saying so.
Closures
When I wrote that Python has “no closures,” I was completely wrong. Thankyou to Hans for pointing this out so kindly. What I meant to say was “Python doesn’t has have Smalltalk (or Ruby or Lisp) style block-closures.” As Hans points out, Python’s approach is still quite flexible, despite the long-winded syntax.
Documentation
I also wrote that the Python documentation is “out of date”. That is wrong. the new Python 2.3 Language Reference and Library Reference manual are both up to date with new-style classes and attributes. The tutorial still neglects to mention the existence of the object class, but this is a small thing.
I had based my statement on the Python 2.2 documentation—which is out of date.
def and class Statements
In Python, def and class are statements rather than declarations, unlike Java, C++ or Pascal. I wrote that this sometimes leads to obscure bugs. Here is a simple example:
class Dog:
dogTracker = AnimalTracker()
def __init__(self):
# ... whatever ...
class AnimalTracker:
# ... whatever…
This code causes an error when the containing module is imported because the assignment to dogTracker in class ‘Dog’ references the variable ‘AnimalTracker’ which hasn’t been defined at that point.
If the assignment to dogTracker were inside the Dog init() method instead, there would be no problem because the code referencing AnimalTracker would not be executed until the init() method is called, which would not be until after the AnimalTracker
This is not an annoyance which affects me every day, but it is one that caught me in my early Python days, and one I end up explaining to people learning Python again and again. On the other hand, Richard Jones points out that Python has many anti-pitfalls for newbies.
Coding Styles
I wrote that “there is no broad agreement on Python coding style.” Integrating with code written elsewhere requres a lot of time looking up not just method names, but their exact spelling (smallCamelCase, BigCamelCase, or with_underscores). Richard points to PEP-008, probably the closest thing that Python has to a universal coding standard. But PEP-008 is not widely accepted. One does not have to go far to find code that doesn’t comply:
All of this code looks straight-forward and well written, so maintenance is not the issue here. The problems only start when trying to integrate codebases that used different standards.
It would be nice if Pythoneers could just agree on One True Coding Standard, as the Java world has done. It is both rare and frustrating to come across code Java that doesn’t largely adhere to Sun’s Code Conventions for the Java Programming Language and the AmbySoft Inc. Coding Standards for Java.
And, Finally
The annoyances I have with Python are minor. I only wrote up a few tiny whinges so that my next “Python is Wonderful” post will look balanced.
Last month, Charles and I were discussing progamming in the “olden days”. This is a game that I win, easily.1
Charles made the observation that any conversation about old hardware tends to descend into some variant of Monty Python’s Four Yorkshiremen sketch, with the punch line becomes “Ones and Zeroes? You were Lucky!”.
At any rate, the conversation go me thinking of the differences between my current PC and the first PC I owned, the Commodore 64.
| Current Machine | C64 | Multiple | |
| Processor Speed | 1.667 GHz | 1MHz | 1667 + The PC’s instructions do more work + More instructions are executed per cycle |
| RAM | 512Mb | 64Kb | 8192. Let’s not talk about memory access speeds. |
| Secondary Storage | Hard disk – 80Gb | Cassette tape – 36kb per C20 | 2.2 Million |
| Secondary Storage Transfer Rate | 58Mbytes/s | 300 baud | 1.9 million |
| Cost per Megabyte | 0.0025AUD | 25.00AUD (10 tapes) | 10,000 |
| Pixels on Screen | 1,470,000 | 64,000 | 23 |
| Colours On Screen | 16Million | 16 | 1,000,000 |
| Modem Speed (Downstream) | 5Mbit (cable) | 1200 | 4,167 |
| Modem Speed (Upstream) | 100kbit | 75 | 1,333 |
| Cost | 2000AUD | 1100AUD (including TV) | 1.8 |
These numbers are mind-blowing. If your mind has not blown, please go back and look at the numbers again. Contemplate what it means to have 2.2 million times as much storage—or 8,000 times as much memory—at one’s disposal.
Note: C64 stats are taken from Phill’s Commodore Page.
1 I haven’t even had to pull out my trump card yet: I ran my first program on a late model acoustic-coupled teletype (similar to “some of these (pictures of teletypes from the Topeka Museum)” that had a built in basic interpreter. It would have been around 1978 or 79. In fact, I seemed to ‘win’ simply by mentioning that I had worked with 8 inch floppy disks.
And if you think I am being petty making a competitive game out of a simple conversation, you need to read this.
I complain about Java, but there are plenty of things to like:
Richard Jones comments on a Melbourne Age article reporting the federal Communications Minister’s suggestion that the ABC become a registered charity.
This is worrying in light of the government’s current attempt to remove funding from charities that are perceived as agitating for change of government policies. One more step down that particular road, and a registered-charity ABC would not be allowed to critically review any policy, announcement or action of the government of the day.
I’d go as far as to say that, if the Liberal party wins another term in 2004, the ABC is dead.
Note: This was written in honour of Post pictures of your cat to Javablogs Day.
They say managing software developers is like herding cats. Looking at my two cats, I see the wisdom in this. It’s a bit of stretch, please bear with me…
Over many, many years, we finally taught our cats not to sit on the lounge. It was a long process, involving simple rules, constant discipline, and a much used trigger squirt bottle.
Here is a picture of number one cat, DJ, not sitting on the lounge.

As you can plainly see, DJ is not—technically—on the lounge. Instead she has found a place to sleep on the headrest. This is better than the lounge because it gets more sun in the mornings. At least when she is up there she doesn’t groom herself, which leaves great gobs of fur to stick to people’s clothes. Plus, sometimes when she wakes up suddenly, she loses her balance and falls off the back of the lounge. Then we can say, “Serves you right, young lady.”
Here is a picture of number two cat, Oscar, also not sitting on the lounge.

Oscar is not on the lounge—he is on a blanket. As usual, Oscar pulled the blanket off the back of the lounge onto the seat so that he could lie on it. We let him get away with this because we can at least wash the fur off the blanket. That, and the fact that we just can’t bear to be continually yelling and squirting him in the face.
Programmers are similar. Given any rule—code reviews, unit tests, getting in before 9:00am, or wearing a tie—we find out exactly how little we can obey it.
I hope my manager doesn’t decide to get a squirt bottle.
Via Ted Leung, a thoughtful essay by Tom Lord on two possible directions for open software.
Tom hammers home the old free as speech vs. free as in beer distinction. He goes on to make the point that free software developers need to think very carefully about how to go about keeping free software, free, and lays out his model for the task.
I really like Python, but there are a few rough edges I would happily see knocked off it.
In the big picture, there are two big problems with Python:
Some language features get up my nose too:
class and def statements for creating classes and functions look like declarations, but their exact effect depends upon the program’s run time state when the class or def statement is run. While very powerful, this can lead to obscure bugs.David also points to 10 Python Pitfalls by Hans Nowak and Python Gotchas by Steve Ferg. Both good reads.
1 Or indeed, whether to use tabs instead of spaces.
A wise man once spake:
All Friday afternoon demos are the same. They go, “Look, I type something in over here, and something happens over there.”
Green’s corollary: The more separate computers, keyboards and displays you have, the better.