May 15th, 2007 | Software development | No Comments
A cool post by Eric Sink on software requirements. I’m currently re-reading Managing Software Requirements, and Eric’s post is much easier going.
You can check out a pre-release of Fortress, SourceGear’s new product for Application Lifecycle Management (ALM). Currently it looks like an issue tracker, but apparently requirements features are in the pipeline. I like the idea of an inexpensive and lightweight tool for this, as I’ve been burned by inadequate requirements before- even on small projects that are being implemented by one or two people. It’s amazing how easy it is to get this wrong.
May 10th, 2007 | Programming | No Comments
Charles Nicholson has a great post up over at Power of Two Games on how to write a proper assert macro in C++.
I’m a big fan of C++, but the fact that Charles has managed to write a 1500 word article on how to write an assert macro is kinda worrying. It never occurred me before, but maybe programmers like C++ because its complicated, not in spite of it.
May 9th, 2007 | Programming | 2 Comments
I’ve been re-reading a few of my favourite programming books over the last couple of months, and I just have to mention this part of The Practice of Programming, by Brian Kernighan and Rob Pike. Not because it’s particularly earth-shattering, but simply because it’s the best explanation I’ve read of how to layout if/else control structures properly.
Sound trivial? It should be, but poor control structure layout is one of my pet hates. I see this sort of thing so often in real code and it grates every time:
if(argc == 3)
if((fin = fopen(argv[2], “r”)) != NULL)
if((fout = fopen(argv[2], “w”)) != NULL) {
while((c = getc(fin)) != EOF)
putc(c, fout);
fclose(fin); fclose(fout);
}
else
printf(”Can’t open output file %s\n, argv[2]);
else
printf(”Can’t open input file %s\n”, argv[1]);
else
printf(”Usage: cp inputfile outputfile\n”);
Actually, I’m being too generous. Imagine the same control structure spread over 200 lines and your’re getting close to the monsters I’ve slain in the past. Kernighan and Pike have this to say about the code:
The sequence of ifs requires us to maintain a mental pushdown stack of what tests were made, so that at the appropriate point we can pop them until we determine the corresponding action (if we can still remember) .
The authors suggest that the correct way to lay out the code for maximum readability is instead:
if(argc != 3)
printf(”Usage: cp inputfile outputfile\n”);
else if ((fin = fopen(argv[1], “r”)) == NULL)
printf(”Can’t open input file %s\n”, argv[1]);
else if ((fout = fopen(argv[2], “w”)) == NULL) {
printf(”Can’t open output file %s\n”, argv[2]);
fclose(fin);
}
else {
while((c = getc(fin) != EOF)
putc (c, fout);
fclose(fin);
fclose(fout);
}
Note how inverting the boolean tests (== becomes !=) allows the code to be greatly simplified. I find that if this technique is used in conjunction with short, well contained functions, it’s often not necessary to use else at all. Instead, if a test fails, the function returns immediately.
Kernighan and Pike provide a well-worded summary of the principle:
The rule is to follow each decision as closely as possible by its associated action. Or, to put it another way, each time you make a test, do something.
May 8th, 2007 | Tools | No Comments
I asked about my previously discussed problems with daemon(1) and ssh on the daemon-users list, and received a very prompt reply from Raf (thanks Raf!). Apparently the solution is to use the -t option to ssh. This is described in the man page as:
Force pseudo-tty allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g., when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.
Because -t forces ssh to allocate a pseudo-terminal, daemon’s stdin will no longer be a socket, so it won’t think it’s being started from inetd. It will then fork() and the ssh session will end immediately as desired.
May 6th, 2007 | Tools | 2 Comments
About a month back Jeff Atwood blogged about Chris Pederick’s Web Developer Extension. I thought it looked cool at the time and since I have been doing a bit of CSS work on this blog, I installed it a couple of weeks ago. This thing is the bomb, especially for a knuckles-dragging-on-the-ground standard web developer like myself. I have been using it to figure out which parts of the CSS stylesheet are influencing the appearance of an element on the page, and it makes this task much, much easier.
May 6th, 2007 | Friends | 1 Comment
Last month I was lucky enough to attend the beautiful wedding of Sergio Corona and Emily Ravenscroft. The wedding was held at Pier 4, Walsh Bay, which was a - dare I say it - magical venue. My friend Karizy has now put up some photos over at flickr, including rare shots of me wearing a tie.
This one shows me (on the right) and Marek hanging on the balcony.

May 6th, 2007 | Friends | 2 Comments
For the last 7 months or so my girlfriend Deonie has been living with Tanya Bailey, one of Australia’s top female BMX riders. This weekend Tanya has been in beautiful Lake Macquarie for the 2007 BMX Australia National Championships. Deonie sent me a text an hour ago saying that Tanya has taken out first place in the Elite Women category. Go Tan! You ROCK!
Press coverage has been, ummm, light, although the results are mentioned over at bmxmania.com. I also found an interview with Tanya from last year over at BMX Ultra. Even though I’ve met her several times, I didn’t know that Tanya likes Spiderbait and The Gurge, which makes her even cooler.
May 4th, 2007 | Software development | No Comments
I coworker of mine is currently reading J2EE Development without EJB, and today he pointed out a couple of very nice quotes from C.A.R. Hoare that are included in a chapter entitled “The Simplicity Dividend”. The quotes are from Hoare’s speech at the 1980 ACM Annual Conference, where he was presented with the ACM Turing Award for that year.
In the first quote, Hoare relates his reaction to a specification for a new version of ALGOL in 1965:
I gave desperate warnings against the obscurity, the complexity, and overambition of the new design, but my warnings went unheeded. I conclude that there are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies.
The first method is far more difficult. It demands the same skill, devotion, insight, and even inspiration as the discovery of the simple physical laws which underlie the complex phenomena of nature. It also requires a willingness to accept objectives which are limited by physical, logical, and technological constraints, and to accept a compromise when conflicting objectives cannot be met.
In the second quote, Hoare gives his opinion on the lengthy project that eventually produced the PL/I programming language:
At first I hoped that such a technically unsound project would collapse but I soon realized it was doomed to success. Almost anything in software can be implemented, sold, and even used given enough determination. There is nothing a mere scientist can say that will stand against the flood of a hundred million dollars. But there is one quality that cannot be purchased in this way–and that is reliability. The price of reliability is the pursuit of the utmost simplicity. It is a price which the very rich find most hard to pay.
And one last quote, not included in the book, shows that even a career as stellar as Hoare’s had its share of failures:
There was no escape: The entire Elliott 503 Mark II software project had to be abandoned, and with it, over thirty man-years of programming effort, equivalent to nearly one man’s active working life, and I was responsible, both as designer and as manager, for wasting it.
This project spanned several years in the mid-60s. Hoare was doing commercial software development in the days before it was widely appreciated just how challenging software can be, and the whole speech is well worth reading to get the flavor of those times.
May 4th, 2007 | Tools | No Comments
I recently came across daemon(1), a neat little GPL utility that will turn any program into a proper daemon. Doing this usually requires a series of calls to semi-obscure POSIX API functions. This is not hard, but only fun the first few times you do it.
Say I have random Perl script foo.pl that I want to run in the background as a daemon. This can be done with a simple command like:
$ daemon –pidfile /var/run/foo.pid –name foo foo.pl
Presuming, of course, that foo.pl is in my $PATH. daemon will fork(), become a session leader, chdir() to /, and do a bunch of other stuff that is well described in Chapter 13 of Advanced Programming in the Unix Environment. daemon then runs foo.pl and waits for it to terminate.
Things now get interesting because I can do:
$ daemon –pidfile /var/run/foo.pid –name foo –running
Which will exit immediately with an exit status of 0 if foo.pl is running and 1 if it’s not. Once foo.pl has served my nefarious purposes, it can be easily stopped:
$ daemon –pidfile /var/run/foo.pid –name foo –stop
daemon can do many other useful things that are well described in the man page.
I liked daemon so much I thought I’d use it to run a daemon on a remote host from a Perl script. Doing this requires a bit of Perl that looks something like:
my $dir = `pwd`;
chomp $dir;
`ssh remotehost daemon –pidfile $dir/foo.pid
–name foo-daemon $dir/foo.pl`;
The only problem with this is that it doesn’t work. daemon decides that it’s not going to fork(), so my Perl script waits for foo.pl to exit rather than running it in the background. A bit of rumaging around the source soon revealed the reason why. daemon plays nice with init(8) and inetd(8), and it knows not to become a daemon if started by either of these programs- essentially because such things will have already been taken care of.
The check to see if daemon has been started by inetd(8) is actually done in libslack and is implemented by the following function:
int daemon_started_by_inetd(void)
{
size_t optlen = sizeof(int);
int optval;
return (getsockopt(STDIN_FILENO, SOL_SOCKET,
SO_TYPE, &optval, (void *)&optlen) == 0);
}
So if standard input is a socket which is apparently the case when daemon has been run by sshd(8), daemon assumes it has been started from inetd(8) and doesn’t do its whole daemonization routine. Annoying. I tested this by modifying daemon_started_by_inetd() so that it always returns 0, and sure enough things worked fine.
Personally I think this is a perfect excuse for a new option for daemon. I’ll have to ask if they will accept a patch. I am a little surprised that no-one has run into this before- I doubt that I’m the only guy writing grubby little Perl scripts that need to run stuff on multiple hosts. More likely there are other ways to do it just as well, or better.
May 3rd, 2007 | Tools, Software development | No Comments
Jason has an interesting post up over at a little madness on the new “personal builds” feature in Pulse.
By way of background, I used to work with Jason at Sensory Networks before he departed to found zutubi and work on Pulse full time. We used Pulse at Sensory to do our builds and I liked it- I prefer it to Cruise Control, the other CI tool I’ve used.
The part that got my attention was this:
Personal builds allow individual developers to submit their changes to Pulse for testing before committing to version control. Pulse does a build and test of the latest version with the developer’s changes applied … personal builds also allow other powerful usage patterns, such as using the distributed building features of Pulse to test across multiple platforms before checking in.
Hot damn! This sounds great. At Sensory, we supported multiple Linux distros and it was quite annoying how often a change that worked fine on Debian broke the RHEL build, or vice versa. Of course, all changes broke the Redhat 9 build, it’s part of the license agreement.
At my current employer we also do builds on multiple platforms, and it’s not much more fun that it was at Sensory.
Ideally you would build and test on all platforms before committing a change, but the time to do this is prohibitive- a couple of hours, at least. Being able to automatically test builds on all platforms before checkin would get round the cross-platform build problem.