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.