Friday, May 16, 2008

Fred Fish' wonderful idea

/*
* FILE
* dbug.h user include file for programs using the dbug package
*
* AUTHOR
* Fred Fish
* (Currently employed by Motorola Computer Division, Tempe, Az.)
* hao!noao!mcdsun!fnf
*/

Fred Fish was a well-loved Amiga programmer. Back in 1987 (yes, we did have computers back then),he wrote and released this marvelous dbug macro package.

(In case you're wondering, that list of names with exclamation marks between them is how we used to give our e-mail address. It's called a "bang path", and each entry is a machine that is capable of exchanging e-mail with the next machine. The last entry -- fnf -- would be Fred's e-mail id. I am very grateful for user@machine.domain addresses!)

Fred's idea was to incorporate the debugging print statements permanently in the code. That is nothing spectacular in itself, but the clever thing he did was allow the programmer to tag the individual debugging statements with text literal tags. For example, if you were monitoring the progress of a network connection in C, you might include a line such as:

  s = socket( PF_UNIX, SOCK_STREAM, 0 );
if ( s == -1 ) {
DBUG_PRINT( "sock", ("Main socket opening did not work!") );
perror( "socket" );
exit( -1 );
}


A method is provided for accepting a list of tags to activate via the command line. So, if you were having trouble with this program and its sockets, you could specify the "sock" debug flag (by convention, the argument was "-# d,sock") and all DBUG_PRINT statements tagged with "sock" would run. You could specify one or more tags to activate, allowing you to choose specific subsegments
of the system to test.

bash$ ./testprogram -# d,sock
sock: Main socket opening did not work!
socket: Connection refused


In addition to DBUG_PRINT, there was DBUG_ENTER( "module" ) and DBUG_RETURN which allowed run-time tracing of the program calls. Add a DBUG_PRINT attached to a "trace" flag, and you could also print out the arguments. DBUG_EXECUTE allowed you to connect an executable code fragment with a debugging tag.

I have used this concept, if not this implementation, in almost every major system I have constructed over the past 20 years. And every time I didn't use it, I regretted it. The ability to tap into logical streams within the program, for example, tracing network io, or memory allocation, or database connections, has been a lifesaver on more than one occasion. The second best approach -- using a numeric verbosity level -- is a pale imitation of this functionality.

Now, granted the original implementation needed to be extended. I've modified the system to accept and identify multiple threads, to permit multiple instantiation of objects, and to use symbolic flags instead of text literals, but the idea remains the same: logically group debugging statements under symbolic tags.

Whether small basic servers, or real-time microsecond-sensitive control systems, Fred's idea of logical debugging tags combined with run-time selection of those tags, has been a wonderful boon to me. And in researching (well, googling) other uses of his package, I was surprised and yet not surprised to find this 21 year old idea implemented in modern packages such as MySQL and dmake.

Learn a lesson from the Fish: symbolic, logical tagging of permanent debugging structures will provide great value to you and your users!

Thanks, Fred.

No comments: