generalnmx
Playful/Fascist Mod
Lemme give you a sample from GPFM (parts of which I am reusing):
What do those functions do? Can you easily determine from the onset? You probably won't be surprised to know, that the headers don't have any prototype information. Anyone looking at this code basically has to run through and figure it out for themselves.
No, I don't need help understanding this code (now, anyway). It just frustrates me to see this type of behavior in aspiring, and even worse, current developers. Why do the best coders seem to shy anyway from even the most minimal documentation?
I am not putting the author of this code on a crux (especially since I don't even know their name, as it was not available anywhere I could find). In fact, it may be unfair of me, as I believe English is not the author's native language. I am just using this code as an example. I truly have deep respect for this author's coding skills.
Here is a sample of my code for comparison. Please bear with me.
While I admit that I may like its format better, I cannot say it represents the "best" design. Nor can I even generalize by saying it is a "good" design. Really, design in C may seem rather silly since it's a functional language, but I think at least some practices should be upkept. At least documentation. Here are my minimal expectations: Everything not intuitive has a short blurb about its purpose. That covers from function prototypes to what "#DEFINE __MOOGAR__" is for. Then the question is, what should be considered "intuitive"? Perhaps you think everything is intuitive and nothing needs comments. I think you're wrong, but maybe I'm wrong. I think comments and design should be tackled from the perspective that people other than you may be viewing your code. If it isn't documented somewhere else, than you should do it.
Really, I'm not here to bitch about other people's habits and styles. I am just curious. Maybe I am wrong about what I consider "good design". For those that want to know my personal views with C (and not just what I consider minimum expectations for everyone), here they are:
- Anything I think is not intuitive should be labled appropriately. (can you guess what "void0 IGameDiamondMove(POINT *pt, ubyte8 dir)" does or the variable "SPRITEINFO.SpriteRow" is for?)
- All function names should start with the name of the header they originate. (Example: AccountsDatabaseLoad from accounts.h), UNLESS they are a utility function for a simple structure, in which case it should start with the name of the structure, followed by an underscore.
- All functions names should start with a capital letter and capitalize each word in the name (example above).
- No underscores in function names UNLESS it is a utility function for a structure.(in C++ you don't have this problem because you can overload operators inside classes). I know you can add pointers to functions inside of structures, but I don't want to add more space requirements then necessary.
- In the case of actions upon an object or entity, function names should be organized like this: AccountsDatabaseLoad instead of AccountsLoadDatabase (this is because of insisting on the "Accounts" addition). "Database" is the entity here, so "Load" should be an action upon that entity (a subset). "All the functions that load something" doesn't sound as good as "Functions that manipulate the Database entity". An example with multiple subsets (besides "Accounts") is "AccountsDatabaseInputParse" instead of "AccountsDatabaseParseInput".
- All ending scopes more then a decent amount of characters should explain what they are ending (like "} // end if" ). Always do it at the end of functions, and at the end of scopes less then three lines apart.
- else statements should have a little blurb explaining what condition they are specifically designed for (possibly just the negative of the if statement)
- Variables should not contain any underscores. Instead of "map_width", use "mapWidth". When adding attributes (like "e" for extern'd or "b" for boolean), it should look like "eMapWidth" or "iMapWidth" (where "i" means "integer").
- Everything that is "externable" (allowed to be used in other files, but declared locally), should have an "e" before the name.
- #defines should always be ALL caps. #else and #endif should follow the same rules as else and ending a scope. #defines that are used as "options" for compiling (such as using certain code) should have two underscores preceeding it (ie, "#define __BLAH").
I'm getting sleepy so I'll stop here (I worked on this post off and on), but I think that's all of it. I want to remind everyone reading up to this point that I, in no way, expect anyone to follow all of these rules. They're just the way I like things. Maybe my design is confusing to other people, or cumbersome. I'd also like to know if you feel that way.
Oh, and if you're wondering why anyone can type so much, I can type around 70 WPM or even higher. I don't use the "Home Key" method, so I have never gotten carpel tunnel syndrome from any position, yet my WPM is kinda variable. The highest I sometimes go up to is 100 WPM. Maybe this also has something to do with me not caring how long a function name is (as long as it is less then 15 letters, or an alt is given of course).
Code:
void ShowImageView(void)
{
char szText[80];
if (gpDrawMode == VIEW_FIT)
{
GpFill(0, 0, 321, 241, 0x00);
PutFitPage(gpViewImage, gpDrawCount);
}
else if (gpDrawMode == VIEW_DESKTOP)
{
if (gpViewImage->Width < 320 || gpViewImage->Height < 240)
GpFill(0, 0, 321, 241, 0x00);
PutDesktopImageOffset(gpViewRight - gpViewCol, gpViewBottom - gpViewRow, gpViewImage, gpDrawCount);
}
else
{
if (gpViewImage->Width < 320 || gpViewImage->Height < 229)
GpFill(0, 0, 321, 229, 0x00);
PutImageOffset(gpViewRight - gpViewCol, gpViewBottom - gpViewRow, gpViewImage, gpDrawCount);
GpFill(0, 229, 320, 11, COLOR_MAGENTA);
// Line count
GpTextOutXY(4, 229, gpImageViewFileName + 3, 0x0f);
gm_sprintf(szText, "%dx%dx%d [%3d]", gpViewImage->Width, gpViewImage->Height, gpViewImage->BPP, gpViewAccel);
GpTextOutXY(310 - (strlen(szText) * 6), 229, szText, 0x0f);
}
}
What do those functions do? Can you easily determine from the onset? You probably won't be surprised to know, that the headers don't have any prototype information. Anyone looking at this code basically has to run through and figure it out for themselves.
No, I don't need help understanding this code (now, anyway). It just frustrates me to see this type of behavior in aspiring, and even worse, current developers. Why do the best coders seem to shy anyway from even the most minimal documentation?
I am not putting the author of this code on a crux (especially since I don't even know their name, as it was not available anywhere I could find). In fact, it may be unfair of me, as I believe English is not the author's native language. I am just using this code as an example. I truly have deep respect for this author's coding skills.
Here is a sample of my code for comparison. Please bear with me.
Code:
/* Setup a new TileMap with given maximums */
void0 IGameMapInit(ubyte8 width, ubyte8 height)
{
int32 y, x;
if (width <= MAP_MAX_WIDTH)
eMapWidth = width;
if (height <= MAP_MAX_HEIGHT)
eMapHeight = height;
eTileMap = (TILEINFO2DARRAY)ISystemMemoryAllocate( sizeof(TILEINFO) * (eMapWidth * eMapHeight) );
for (y = 0; y < eMapHeight; y++)
for (x = 0; x < eMapWidth; x++)
{
eTileMap[x][y].tileNum = rand() % 3; /* cannot be greater then MAX_TILENUM */
eTileMap[x][y].blendTileNum = MAX_TILENUM; /* means no blended tile here */
eTileMap[x][y].bgSpriteNum = MAX_SPRITENUM; /* means no sprite located here */
eTileMap[x][y].ptrSpriteNum = NULL; /* means no player sprite located here */
eTileMap[x][y].SpriteRow = 0;
}
} /* end of IGameMapInit() */
While I admit that I may like its format better, I cannot say it represents the "best" design. Nor can I even generalize by saying it is a "good" design. Really, design in C may seem rather silly since it's a functional language, but I think at least some practices should be upkept. At least documentation. Here are my minimal expectations: Everything not intuitive has a short blurb about its purpose. That covers from function prototypes to what "#DEFINE __MOOGAR__" is for. Then the question is, what should be considered "intuitive"? Perhaps you think everything is intuitive and nothing needs comments. I think you're wrong, but maybe I'm wrong. I think comments and design should be tackled from the perspective that people other than you may be viewing your code. If it isn't documented somewhere else, than you should do it.
Really, I'm not here to bitch about other people's habits and styles. I am just curious. Maybe I am wrong about what I consider "good design". For those that want to know my personal views with C (and not just what I consider minimum expectations for everyone), here they are:
- Anything I think is not intuitive should be labled appropriately. (can you guess what "void0 IGameDiamondMove(POINT *pt, ubyte8 dir)" does or the variable "SPRITEINFO.SpriteRow" is for?)
- All function names should start with the name of the header they originate. (Example: AccountsDatabaseLoad from accounts.h), UNLESS they are a utility function for a simple structure, in which case it should start with the name of the structure, followed by an underscore.
- All functions names should start with a capital letter and capitalize each word in the name (example above).
- No underscores in function names UNLESS it is a utility function for a structure.(in C++ you don't have this problem because you can overload operators inside classes). I know you can add pointers to functions inside of structures, but I don't want to add more space requirements then necessary.
- In the case of actions upon an object or entity, function names should be organized like this: AccountsDatabaseLoad instead of AccountsLoadDatabase (this is because of insisting on the "Accounts" addition). "Database" is the entity here, so "Load" should be an action upon that entity (a subset). "All the functions that load something" doesn't sound as good as "Functions that manipulate the Database entity". An example with multiple subsets (besides "Accounts") is "AccountsDatabaseInputParse" instead of "AccountsDatabaseParseInput".
- All ending scopes more then a decent amount of characters should explain what they are ending (like "} // end if" ). Always do it at the end of functions, and at the end of scopes less then three lines apart.
- else statements should have a little blurb explaining what condition they are specifically designed for (possibly just the negative of the if statement)
- Variables should not contain any underscores. Instead of "map_width", use "mapWidth". When adding attributes (like "e" for extern'd or "b" for boolean), it should look like "eMapWidth" or "iMapWidth" (where "i" means "integer").
- Everything that is "externable" (allowed to be used in other files, but declared locally), should have an "e" before the name.
- #defines should always be ALL caps. #else and #endif should follow the same rules as else and ending a scope. #defines that are used as "options" for compiling (such as using certain code) should have two underscores preceeding it (ie, "#define __BLAH").
I'm getting sleepy so I'll stop here (I worked on this post off and on), but I think that's all of it. I want to remind everyone reading up to this point that I, in no way, expect anyone to follow all of these rules. They're just the way I like things. Maybe my design is confusing to other people, or cumbersome. I'd also like to know if you feel that way.
Oh, and if you're wondering why anyone can type so much, I can type around 70 WPM or even higher. I don't use the "Home Key" method, so I have never gotten carpel tunnel syndrome from any position, yet my WPM is kinda variable. The highest I sometimes go up to is 100 WPM. Maybe this also has something to do with me not caring how long a function name is (as long as it is less then 15 letters, or an alt is given of course).