Tuesday, November 09, 2004 10:09 AM
LarryOsterman
What does style look like?
Building on my
post on style last week.
So what does "coding style" look like, anyway?
Well, the facile answer is "I know it when I see it". But it's more than that. A good coding style should result in high quality self-documented code that is esthetically pleasing to look at. This is not to reduce the value of external specifications, they are utterly critical to the success of a project, but external specifications serve a different purpose from the code. Neither can function independently.
I thought it might be interesting to see what happens to a single piece of code when you use different styles on it.
For the purposes of illustration, I opened my copy of Robert Sedgewick's "Algorithms in C, 3rd edition" to a random page, and picked the most reasonable example from that page. On that page is the following code:
#include "list.h"
main(int argc, char *argv[])
{
int i, N = atoi(argv[1]), M = atoi(argv[2]);
Node t, x; initNodes(N);
for (i = 2, x = newNode(1); i <= N; i++)
{ t = newNode(i); insertNext(x, t); x = t; }
while (x != Next(x))
{
for (i = 1; i < M ; i++) x = Next(x);
freeNode(deleteNext(x));
}
printf("%d\n", Item(x));
}
This is the code as it exists in the book, any errors come from my poor transcription efforts.
Let's see what happens to the code if you apply a couple of different coding styles. Please note: there's no one-true coding style. They're all different, and they all have their advantages.
First up, Hungarian. Hungarian's a structure-neutral coding style, so all I did was to hungarian-ize the variables and functions, without touching the other aspects.
#include "list.h"
main(C cArg, SZ rgszArg[])
{
I iNode, cNodes = atoi(rgszArg[1]), cNodesToSkip = atoi(rgszArg[2]);
PNODE pnodeT, pnodeCur; InitNodes(cNodes);
for (iNode = 2, pnodeCur = PnodeNew(1); iNode <= cNodes ; iNode++)
{ pnodeT = PnodeNew(i); InsertNext(pnodeCur, pnodeT); pnodeCur = pnodeT; }
while (pnodeCur != PnodeNext(x))
{
for (iNode = 1; iNode < cNodesToSkip ; iNode++) pnodeCur = PnodeNext(pnodeCur);
FreeNode(PnodeDeleteNext(pnodeCur));
}
printf("%d\n", Item(nodeCur));
}
So what changed? First off, all the built-in types are gone. Hungarian can use them, but not for most reasons. Next, the hungarian types "I", "C", and "SZ" are used to replace indexes, counts and strings. Obviously the C runtime library functions remain the same. Next, I applied the appropriate prefix - i for indices, c for counts, p<type> for "pointer to <type>". The Node type was renamed PNODE, in Hungarian, all types are uppercased. In Hungarian, the name of the routine describes the return value - so a routine that returns a "pointer to foo" is named "Pfoo<something relevent to which pfoo is being returned>".
Looking at the transformation, I'm not sure it's made the code any easier to read, or more maintainable. The next examples will try to improve things.