afongen
Sam Buchanan's weblog.

GPGMail

GPGMail , a GnuPG plugin for Apple's Mail.app, went 1.0 the other day, which reminded me to install it so I could start using PGP again. First I had to get MacGPG going, but that was a snap. I was up and running in about five minutes. That's the way it should be.

One thing that I like about the MacGPG apps is that the GUI functions open up a terminal window, so I see the gpg commands. That's one way to learn 'em. And I really like how GPGMail integrates with Mail. Very pleased, I am.

chomp

Gah. I just spent more time than I'd care to admit working on a stupid little bug. I'm writing a module that opens up a socket, sends a request (remote procedure call, really) as XML, gets an XML response, and closes the socket. Simple enough, except that the XML I was getting back didn't quite seem right. It looked fine if I picked it off the stream byte by byte, but if I just slurped the whole thing up ($str = <$socket> — it's just a couple hundred bytes, after all) it was all messed up. At first I figured maybe it was a buffering problem, even though that didn't quite make sense, but no. I tried to grab the response line by line:

$/ = CR;
while (my $buf = <$socket>( {
  $response .= $buf;
}

But no. When I tried to print "$response\n", it was a mangled mess. My tests were fine, but it didn't look right.

You're probably seeing the problem already: I wasn't stripping the carriage return, so it didn't print properly on Windows or Unix, which use CRLF and LF, respectively. Duh.

$/ = CR;
while (my $buf = <$socket>( {
 chomp $buf;
 $response .= $buf;
}

Dumb, dumb, dumb. This is the sort of thing that I would have picked up on right away, were I not scattered across too many projects for me to focus properly. I should have trusted my tests and just moved on. I'm not sure why I felt compelled to print the response to the terminal, in the first place. This'll teach me.

Quirksmode

Another one for the bookmarks: Peter-Paul Koch's Quirksmode.

Panther Envy

Somehow I managed not to be at the Apple Store tonight for the Panther release. I would have had to settle for the store at Southdale anyway, since the one at the Mall of America is closed for remodelling (!). The Southdale Apple store is fine — I stood in line for its grand opening, no regrets — but a bit dinky. Besides, I don't feel that I can drop $130 right now. So I shall wait for Panther, at least until next payday, and live vicariously.

Test-Driven Development

I've been doing test-driven development for several months now and am not looking back. I don't remember what first inspired me to read Kent Beck's book on the subject, but I sure am glad I did.

I was already sold on the idea of unit tests. (These are tests for individual units of code — be they methods, classes, or what have you. If you've ever installed a CPAN module or run make test, you've seen unit tests at work.) However, they had not yet wormed their way into my actual coding practices. You know how it is: sure they're a good idea, but when would I have time? This was part of the initial appeal of TDD. By writing the tests before the code being tested, I'm guaranteed to have tests.

This is far from the only benefit, though, or even the most important one. Testing my code before I write it makes me carefully and continually work through the design, facilitating exploration of interesting ideas and discard clearly ridiculous ones before I get too far into them. I've found that TDD helps me develop cleaner, more robust code. Writing implementations for an interface before I've even written the interface helps expose flaws and vulnerabilities that I likely would not have discovered until much later.

It's difficult to understand until you've tried it for a while. But I really do write better code this way.

Sound confident? Yep. Beck writes a lot about how the test-driven cycle improves programmer confidence because of the immediate feedback and stream of small successes. Pragmatic Programmers Dave Hunt and Andrew Thomas also suggest test-first model as a way of breaking through the fear of the blank page (er, empty buffer). Start by writing a simple test, so simple that you wouldn't normally bother.

The advantage to starting with such a trivial test is that it helps fill in the blank canvas without facing the distraction of trying to write production code. By just writing this very simple test, you have to get a certain level of infrastructure in place and answer the dozen or so typical startup questions: What do I call it? Where do I put it in the development tree? You have to add it to version control, and possibly to the build and/or release procedures. Suddenly, a very simple test doesn't look so simple any more. So ignore the exquisite logic of the routine you are about to write, and get the one-line test to compile and work first. Once that test passes, you can now proceed to fill in the canvas — it's not blank anymore. You're not writing anything from scratch, you're just adding a few routines…. ("The Art in Computer Programming" (PDF).)

Kimbro Staken recently wrote about encountering programmer's block. TDD is one way I handle this situation. It just helps me start doing stuff. If I could convince someone to pair program with me, I think that would help, too.

A coworker agrees TDD is interesting and he's certainly all for unit tests, but considers TDD a waste of time when just experimenting. On the contrary, I think that experimentation is exactly when TDD is needed. Sure, if I'm writing a one-off script, there's no need to write a test. But if I'm putting some effort into experimenting, maybe half a day or more, TDD is worthwhile because of how it supports exploration of ideas. Rather than first writing a class, then discovering the mistakes I made in designing its interface, I implement the interface right away and figure out what makes sense and what doesn't. Once I fall into a rhythm (test, code, test, refactor), experimentation goes faster.

An essential part of TDD is refactoring to simplify and make designs cleaner. So TDD is also a useful introduction to refactoring (next up for me: read Fowler's Refactoring). Because of this, TDD also served as my entrée into agile software development, in particular Extreme Programming. I'll probably write more about this before long. Here's a quick list of current influences:

XForms

I have such high hopes for XForms. I'm working on a project right now for which they would have proven extremely useful, but after investigating existing XForms engines and what it would take to get rolling, I decided that the project deadlines precluded my using them. Pity, because they're very cool and very useful. I feel this way even after slogging my way through the hype.

And now they're a W3C recommendation. Along with this announcement, we are given the handy XForms for HTML Authors. Now I've just got to start getting those deadlines sorted out…

Simple Test Rocks

If you're looking to try unit testing in PHP, I cannot recommend Marcus Baker's Simple Test highly enough. There are several good unit testing frameworks for PHP, (most of them, including PEAR's, cryptically named PHPUnit) but once I tried Simple Test I stuck with it, for one basic reason: documentation.

Unusually well developed documentation was what first drew me to SimpleUnit. Not only is the API outlined in detail, but there's an introductory tutorial to unit testing and test-driven development, with plenty of examples of how to use Simple Test. I was up and running in no time and was immediately hooked. Take this as a lesson: clear documentation attracts users/developers.

Mock object support is a nice bonus, too. Mock objects support unit testing by simulating real objects that are too difficult to set up and take down. By coding to an interface, and substituting a mock object that uses that same interface, you can more effectively test an individual unit. For a quick, accessible overview, Simple Test's documentation works well, and I also suggest a sample chapter (PDF) from Andrew Hunt and David Thomas's just-published Pragmatic Unit Testing. Simple Test is no longer the only PHP testing framework to offer mock object support, although I believe it was the first and was another reason I stuck with it.

The piracy problem is not where they claim it is.

In Analysis of Security Vulnerabilities in the Movie Production and Distribution Process, it's demonstrated that most movies available for download on the Internet are not pirated DVDs, but leaked by industry insiders.

LOTR Trilogy

I was just talking with someone about how very cool it would be to have a screening of the entire Lord of the Rings trilogy, and whaddya know, they're doing it.

Now, are they doing the same thing for The Matrix? Seeing Revolutions at an IMAX theatre will be cool. Seeing all three at once at the IMAX would be mind-blowing.

<dl> for forms.

I've reconciled myself to using tables to lay out forms, consoled by the idea that forms can be considered "interactive tabular data." — fully aware that's just an excuse, something I tell myself so I feel better (not so guilty). Richard Rutter suggests using definition lists. An interesting and satisfying idea, one I began to give serious consideration, trying to decide which technique I prefer. Then I realized something.

It doesn't matter.

Sometimes, definition lists make semantic and practical sense in forms. I'm grateful for the idea. Sometimes, tables are more appropriate because the form is indeed tabular data. Sometimes mixing the two may be better. When it comes to doing the work, I'll choose whatever is most appropriate to the content.

And in a year or two, I'll look back at this and marvel at how naive I was.

Sometimes Things Are Too Easy

I've started work on a project in which I need to generate bar graphs, so naturally I turned to GD::Graph, a Perl module for doing just that. I expected that when I created my first image, I'd be excited to have accomplished something moderately difficult (or at least typing-intensive) like creating an image out of nowhere. But it was too easy. It only took a few minutes before I had my first PNG. How terribly unsatisfying. :-)

Welcome, Jacob.

Congratulations to our friends Jim & Camille Holthaus on the birth of their son Jacob. And to their first son, Robert, who now has a little brother to play with.

Another reason to use Firebird.

One by one, my coworkers are switching to Firebird. A few have been using IE, most were Netscape users. It's been fun listening to them comment to one another as they switch about how very cool it is.

Oh yeah.

For those who still use IE as their default browser, I point to my demonstration of the dangers of HTML mail. I've just added to the demo, taking advantage of the fact that IE has access to clipboard contents (via Tim McGuire).

The fun never ends.

Don't buy this car.

A guy at work (let's call him Mike. It's his name.) just sold his Porsche. The car is sitting in his garage, waiting for the shippers to pick it up, when he finds the car being sold in eBay. Only it isn't being sold by the new owner. Whoever's making this fraudulent sale even set up a Geocities web page that copies word-for-word Mike's web page about the car. The photo on eBay? That's Mike's front yard.

Not sure how long this will stay up on eBay, take a peek while you can.

Must read faster.

The problem with library books is that when I buy a book that I very badly want to read (say, Neal Stephenson's Quicksilver), I feel compelled to finish the library books first. This isn't really a problem since I read pretty fast, but I start to resent the books that I'm trying to blow through. They're holding me back. Hennepin County Libraries make it very easy to renew online, but lately I've been unable to renew the books because someone else has them reserved.

So this weekend, I must finish The Overseer. This could be tricky, as I never have the reading time that I want on the weekends.

MFA in software might get somewhere

As mentioned before, Richard Gabriel has been promoting the idea of a Master of Fine Arts in Software.

It looks like it might actually happen: the University of Illinois is seriously considering the idea.

I've suggested the idea to computer science faculty I know, but they just smile tolerantly at me, amused that I could be so droll. Clearly I'm talking to the wrong people.

Blog this.

I'm learning that if I don't mention something here within a couple days of thinking of it, it might be months before I get around to it.