The Deadline – A Novel about Project Management

Dimitris sent me “The Deadline” as a gift for my birthday. Written by Tom DeMarco (author of “Peopleware“) it is a novel that aims to introduce the reader to the complicate and cruel world of software project management. It also explains why most software projects fail. Clearly. In a buy-this-book-for-your-manager-to-open-his-eyes way. Team formation, design, quality control, unrealistic deadlines, goals and schedules, it is all in there. So if you need psychological support when a project goes bad, you should read the book. It is a good bus read.

It is also a book that opens doors to new worlds. Thanks to the book I learned about the adventures of Mr. Tompkins by George Gamow in which he aims to explain modern scientific theories to a popular audience. I see my stack of unread books getting higher again. I also learned about iThink which seems pretty cool (but then again I find Systems Thinking interesting enough). Pity though that iThink costs as much as it does (should I write my half-baked hack of systems thinking software? Damn! When I cannot buy, I try to write code instead and thus pay in time).

What would I change in the book? I would completely discard the very last chapter. Totally unnecessary. But no harm done, since the story is only the vehicle for the project management message and the message does get through. I’ve been lucky enough to have worked with managers like Mr. Tompkins; for this I want to end this post with the very first notes in Mr. Tompkins’s journal:

Four essentials of Good Management:

  • Get the right people
  • Match them to the right jobs
  • Keep them motivated
  • Help their teams to jell and stay jelled

(All the rest is Administrivia)

Amen to that!

ORA-24550

When you get an ORA-24550, it might be because there’s a NULL returned from a SELECT statement that your code is not handling properly (like a string pointer equal to NULL instead of pointing to “”).

My review on “Algorithms on strings”

My review on “Algorithms on strings” (for which I’ve blogged before) for the ACM SIGACT News is out. There’s a typographical error though: I did not review “Algorithms on strings” by Dan Gusfield, but “Algorithms on strings” by Crochemore, Hancart and Lecroq.

Thank you Bill Gasarch for the opportunity and thank you for fixing the typo too!

PS: You can download the review PDF from Bill Gasarch’s site.

Update: The review entry is corrected in the ACM site: Like Bill Gasarch wrote to me: “There is no such thing as a final version of anything anymore!

“All models are wrong, but some are useful”

And then there are models which are not useful at all (emphasis mine):

“consider an all-OSS world in which each company offers consumers exactly the same shared code as every other company. By definition no company can then compete by writing more OSS code than its rivals. This lack of competition suppresses code production for the same reason that cartels suppress output.”

Or to put it in other words, because companies compete within a common code base, they contribute less and less code into the project because they run the risk of losing a future contract to a competitor using code they have submitted.

The authors of this study are advised to read the history of the X Window System whose development closely follows their model. X is universal in the Unix world (commercial and open source systems who try to converge by being POSIX compilant (another hint here)), never faced lack of contributors and contributions or even stewardship and whenever stagnated new branches forked and pushed it forward. And while the authors seem to think that Open Source has been with us for the last 20 years, X was born in 1984. In fact we’ve had Open Source software since the very beginning of software.

* The quote used in the title of this post is attributed to statistician George Box.

Update: After this post and a discussion on twitter, Gregory Farmakis performed a mind experiment.

that sounds like a lot of work…

From alpine‘s alpine-2.00/alpine/mailcmd.c:

                switch(r = is_writable_dir(dir)){
                  case 0:               /* exists and is a writable dir */
                    /*
                     * We could figure out if it is empty and use it in
                     * that case, but that sounds like a lot of work, so
                     * just fall through to default.
                     */

                  default:
:
case 3:               /* doesn't exist, that's good! */
:

“SYLK: File format is not valid”

Recently I was involved in a project that required producing a CSV file as output. To convert the output in Microsoft Excel format, I used Google Docs where I uploaded the CSV file and exported it as a .xls. When trying to open the file from Excel, one would get the following (not very helpful) message:

SYLK: File format is not valid

SYLK are files typically used to exchange data between applications. Fortunately, Microsoft has documented the problem:

A SYLK file is a text file that begins with “ID” or “ID_xxxx”, where xxxx is a text string. The first record of a SYLK file is the ID_Number record. When Excel identifies this text at the beginning of a text file, it interprets the file as a SYLK file. Excel tries to convert the file from the SYLK format, but cannot do so because there are no valid SYLK codes after the “ID” characters. Because Excel cannot convert the file, you receive the error message.

The quick workaround to the above is to not use “ID” as the first two characters in the CSV file to be imported. And like the article says, this problem does not occur if the first two letters are lowercase “i” and “d”.

Ah, the joys of report generating. Full of slight annoyances…

c-client callbacks

* This is mostly for personal copy-paste reasons

Those who take the time to develop applications using UW-IMAP (or Panda IMAP) know that there are a number of callbacks that need to be defined. What follows is the simplest (do nothing) version of them.

#include "c-client.h"

void
mm_flags(MAILSTREAM *stream,unsigned long number) {
}

void
mm_status(MAILSTREAM *stream,char *mailbox,MAILSTATUS *status) {
}

void
mm_searched(MAILSTREAM *stream,unsigned long number) {
}

void
mm_exists(MAILSTREAM *stream,unsigned long number) {
}

void
mm_expunged(MAILSTREAM *stream,unsigned long number) {
}

void
mm_list(MAILSTREAM *stream,int delimiter,char *name,long attributes) {
}

void
mm_lsub(MAILSTREAM *stream,int delimiter,char *name,long attributes) {
}

void
mm_notify(MAILSTREAM *stream,char *string,long errflg) {
}

void
mm_log(char *string,long errflg) {
}


void
mm_dlog(char *string) {
}

void
mm_login(NETMBX *mb,char *user,char *pwd,long trial) {
}

void
mm_critical(MAILSTREAM *stream) {
}

void
mm_nocritical(MAILSTREAM *stream) {
}

long
mm_diskerror(MAILSTREAM *stream,long errcode,long serious) {
}

void
mm_fatal(char *string) {
}