80 Comments
- s0m31john, on 10/11/2007, -3/+46HAI
CAN HAS STDIO?
VISIBLE "HAI WORLD!"
KTHXBYE - Vasant56, on 10/11/2007, -2/+34Tip 1: Comment like a smart person.
Tip 2: Use #define a lot. No, a LOT. (meaning (for java users): declare static variables for constants).
Tip 3: Don't use variable names that will mock you.
Tip 4: Do error checking. You make errors. Yes, you.
Tip 5: "Premature optimization is the root of all evil." - Donald Knuth (meaning: don't make your code so efficient you can't understand it_
Tip 6: Don't be too clever by half. (meaning: don't try to write smart code you don't understand) - inactive, on 10/11/2007, -1/+28Professors tend not to be the best coders IRL
- TehDoctor, on 10/11/2007, -0/+23If you're writing C++, #define should (in most cases) be replaced by const so you can have type safety.
@achacha
You apparently can't read. I guarantee Knuth is not an imbecile, especially in comparison to you, since I haven't heard of any of your CS books. Knuth said *premature* optimization is bad. Meaning, write code you can understand first, then profile it to find where it's slow. Then insert your ugly speed hacks. At least now you know what the hell's going on and can throw in a comment to explain why you changed some for loop into a Duff's Device. - UrbanVoyeur, on 10/11/2007, -0/+21The only thing I disagree with is the author's shortening of variable names. Yes, long variable names can be a bit clumsy, but they make understanding the code SO much easier - especially when you are working with a team and people don't comment as much as they should.
I would extend that to function/method names - they should be long enough to summarize the action taken.
Abbreviations are bad - very bad - especially when not all of your coders are native english speakers. I once worked on code that was written by a native Spanish speaker - and all the abbreviation were short versions of Spanish words. On the positive side, my colloquial Spanish improved, but the Chinese, Russian and Indian team members suffered mightily.
And about booleans - it would be nice if every boolean was named as a positive question of the state with only a yes no answer:
bool has_wheels
bool is_linked_to_commander
rather than
bool wheels
bool link_commander
My two cents... - mattmcm, on 10/11/2007, -1/+21Thanks for the quick summary. However, it's good to read this article, because it has a few good code snippets and it uses Space Invaders as an example.
- objc, on 10/11/2007, -0/+18Gotta love IBM's developerWorks articles. This one features some generally common sense tips for most of us, but good reminders for the just getting started crowd.
- friedcalamari, on 10/11/2007, -3/+20My code was hard to write. It should be hard to read.
- LetsGoHawks, on 10/11/2007, -0/+16I had a prof in college who insisted we comment on every line of code. Yes, every one.
It led to things like
*Prof. Jones
*wants us to comment
*every line of code
*so I did
(I had to use the *, I can't remember the comment symbol for Pascal........) - Red5, on 10/11/2007, -0/+13Although old, for the target audience of this article, beginner or recreational developers (not ueber-coders such as yourself, apparently), there stands a good chance they may not have seen this article. Having seen plenty of terrible code that would have benefited greatly from these tips, I'm going to say that this article does not suck and worth the 5 minutes it takes to read and understand. :P
- inkyblue2, on 10/11/2007, -0/+12i would not put #define in this list, because it can create as many problems as it solves. #2 should probably be something more general, like "name and consolidate your constants."
- baalzebub, on 10/11/2007, -0/+12clean elegant code is as much an art as it is a science...
- Red5, on 10/11/2007, -1/+11Instead of using #define as stated in tip #2 it is preferable to use "const" variables. A "defined" value is actually textually substituted by the c/c++ preprocessor in your code then compiled. The end result is that when using a debugger you see only see the value that your defined name represents. By using a "const" value you can actually see the name when viewing variables in your debugger.
If you're concerned about performance, don't be. Decent compilers these days will optimize the const variable away when you allow it to.
Read Effective C++ by Scott Mayers for more tips like these. - swordedge, on 10/11/2007, -0/+8tip 1a, try commenting the code before you write it. This sometimes helps you KISS (keep it simple stupid). Not that I am good at following my own advise.
- batmant, on 10/11/2007, -0/+7This is a good example of why I struggle with us being called Software Engineers. I think Software Artist sounds more appropriate.
Unlike almost every other facet of engineering, we create nothing that is tangible and manifest everything from nothing only bound by our imagination and associative skill. Sounds much more like an artist to me.
Hmm...I do like the salary of an engineer though. - jm9206755, on 10/11/2007, -1/+7Which is why they're professors and not Sergey Brin and Lawrence Page.
- dgendreau, on 10/11/2007, -1/+7@TehDoctor
In C++, I find enum a lot more useful for creating integer constants because It can confine constants to a specific class or namespace scope, like this:
file.Open("foo.txt", CFile::CREATE | CFile::TEXT);
where CREATE and TEXT are declared in a public nameless enum in the CFile class. - TopBanana, on 10/11/2007, -0/+6// This procedure moves the bullet upwards.
Then call it move_upwards.
// It's called NUM_BULLET_MOVES_PER_SECOND times per second.
Leaky abstraction. This function doesn't care how many times per sec it's called. What happens when you change your timing routine? You forget about this comment and it confuses the hell out of someone in six months' time.
//It returns TRUE if the
//bullet is to be erased (because it hit a target or the top of the screen) and FALSE
//otherwise.
Better to have a sensibly named output parameter.
void player_bullet::move_upwards(bool *was_bullet_destroyed)
{
...
} - busta, on 10/11/2007, -0/+6And don't forget that ++i; runs slightly faster. However both are still O(1).
- Philodox, on 10/11/2007, -0/+6My only addendum to that is use #define to create constants, not to make macros. Macros make code an incomprehensible mess.
- swordedge, on 10/11/2007, -0/+5They reference but not point to this in the article. Very worth checking out
http://www.ioccc.org/ - RevEng, on 10/11/2007, -0/+5if (!(file_not_found == true))
program_not_running = false;
And don't anybody not say this hasn't not been done before, because you know that it's false to deny it. - inkyblue2, on 10/11/2007, -0/+5agreed, and add namespacing to the list of reasons why consts are better than #defines. there are too many MAX_LENGTHs in the world to throw them all into the global namespace.
for those of you who for whatever reason are forced to put your named constants in the global namespace, be polite and use a prefix to (a) avoid conflicts and (b) give the user a hint as to where this constant might be found when they come across it in your code somewhere. in other words, when writing fooModule, consider defining FOO_MAX_LENGTH, etc. instead of just MAX_LENGTH. - busta, on 10/11/2007, -0/+5I don't like the way this developer talked about doing error checking. One really powerful tool is the assert statement. Instead of doing if this blah blah blah just to make sure your program is behaving as intended, you simply insert an assert statement that asserts your logic is correct.
E.g. num_points should never be negative, and if it is, your program halts and you go debug what the problem is.
Void change_score(short num_points)
{
assert(num_points > 0);
score += num_points;
make_sparkles_on_score();
} - achacha, on 10/11/2007, -0/+4Wish more people read Scott Mayers books, he had some serious hardcore insight into C++.
- geminitojanus, on 10/11/2007, -0/+4Wouldn't it make more sense to use an unsigned type in this case? Why bother checking the bottom bound, just check the upper bound instead.
- drakethegreat, on 10/11/2007, -0/+4You have to crawl before you can walk. Seriously I don't care if you live in China or Europe, if you don't comment your code or you comment with your foreign language then please don't make it OSS. I hate downloading source or trying to mod something to find that the person named everything temp1-temp10 and has ZERO comments.
- Metasquares, on 10/11/2007, -0/+4Not strong enough - it's more art than science.
- RevEng, on 10/11/2007, -0/+4I agree with pak. He's not saying that he doesn't know the difference between prefix and postfix operators, or that they are particularly difficult to understand, it's simply a matter of recognizing the difference at a glance. It's far too easy to end up with an off-by-one error when mixing pre- and post- operators. Skimming through the code, it's too easy to miss the fact that you wrote a pre and meant a post.
Example: Knuth's strcpy
char *a, *b;
while (*a != 0)
*b++ = *a++;
Not only is it inherently flawed (makes many unsafe assumptions), it's also difficult to understand at a glance (unless you're intimately familiar with the idiom), difficult to debug (three things change on a single line), and difficult to extend (try changing this to strncpy with a single line of code). - zeptobyte, on 10/11/2007, -0/+3Ahh, Spiderweb Software.. I lost so much of my youth on the Exile games..
- PezFr33k, on 10/11/2007, -0/+3This article is all very true, if you're coding in standard C. However, since it claims it's in C++....
Tip1: Yes, this is common sense. But also it's better just to write self explanatory code and document when you're doing crafty things (or sparingly do crafty things...). Also adhere to doxygen style comments for class headers.
Tip2: No, no, no. Define is evil, and should not be used. It's global, and handled by the preprocessor so this can lead to all sorts of horrible things. Use namespaces to avoid collisions, and use const global variables so that the compiler can freak out at you if you happen to redeclare something.
Tip3: Again, namespaces can really help to keep short, meaningful variable names. Tons of abbreviations lead to obfuscation and proliferation of TLAs (Three Letter Acronyms).
Tip4: Ok, I'm a big believer of defensive programming, but my major complaint here is the void return and logging an error. Why must C coders do this?? They spend lots of time being careful and checking for errors, then log an obtuse message never to be seen by the caller. Exceptions where designed to handle these cases and keep code much more readable.
Tip5: I do agree with this one. Just make sure to add timers to your code so that you can profile the bottlenecks later. If you program is suddenly dog slow and you have no profiling, you'll spend hours guessing what could be wrong instead of fixing the five lines of code giving you a headache.
Tip6: Using advanced techniques don't always end up resulting in harder to read code. Obviously using strange tricks in code because they are cool is a waste of time, but if they end up in cleaner code, then I'm all for it. Using the STL for example, can make vast improvements, especially when using algorithms and standard contains. Also, as far as I'm concerned, if you don't know the difference between i++ and ++i, then you shouldn't be coding in C++. There's no excuse not to know it. Yes, this makes C++ harder to use, but it should be. There are many other higher level languages out there that will abstract this for you.
Conclusion: For god's sake, stop telling people to use Hungarian notation. It results in the most hideous code ever written. CamelCase is good, but keeping variable types in the naming is just painful. - Tanouki, on 10/11/2007, -0/+2Tip 7: choose_a_notation_for_your_variables and stickWithItEverywhereInYourCode
- Stonekeeper, on 10/11/2007, -0/+2I can't believe no one has mentioned code complete by Steve McConnell. It's one of the authoritative books on good code writing (Ignore that it is from microsoft press!).
http://cc2e.com/
http://en.wikipedia.org/wiki/Code_Complete
http://www.amazon.com/Code-Complete-Second-Steve-McConnell/dp/0735619670 - dasluvaluva, on 10/11/2007, -1/+3I found that converting alot of my code to NaturalDocs (.org) forced me to clean it up a lot, simply to make it easy enough for others to implement.
- dgendreau, on 10/11/2007, -0/+2Another good rule I have come across over the years:
When naming boolean variables or accessor functions, don't use negative names if you can avoid it (eg. prefer names like "file_is_open" over "file_not_open"). The latter can lead to all kinds of bizarre double negative if statements that are unnecessarily difficult to read. - dgendreau, on 10/11/2007, -0/+2@mandel15
you do realize that assert() and ASSERT() are already ignored in release builds right? - jacekpoplawski, on 10/11/2007, -0/+1I would use exception instead assert.
- Indecision, on 10/11/2007, -1/+2"Then call it move_upwards."
I'm not a C coder, but I'll take a stab at this.
Everything on the screen is an object. There are at least 4 types of object that move: player, bullet, alien, and alien_bullet (I'm making up names). The bullet only moves upwards, the alien_bullet only moves downwards, the player moves left/right, and the alien moves left/right/down.
So, what's easier/better to do at the end of each timing loop? Do you loop through an array of on-screen objects, calling the move_it() member function on a pointer to each? Or do you force yourself to keep track of multiple collections of objects, calling move_up, move_down, move_leftright, or move_leftrightdown depending on the type?
If the latter, what happens when you decide the player should also be able to move up and down? What happens if you add a whole new type of "thing" to the screen? In the former solution, that part of your game loop doesn't have to change. - GyroTech, on 10/11/2007, -0/+1Thank FSM that someone other than me hates hungarian...
I have to work on a project now that some PoS contractor wrote and almost made the company go under. The guy uses some horrible construcs at the best of times but he totally had a hard-on for hungarian (but not even consistently, sometimes his ints are i-prefixed, sometimes n). The times he obvisly had to change a type at some point but cba to change the var name?? Nightmare!! Finding cFoo is acutally a double almost had me walking out of this job. Also he loved to use the mangled windows.h types - WORD instead of short, LPCTSTR instead of wchar_t* GAH!! - mandel15, on 10/11/2007, -1/+2I demand a tag in digg, what a wastd of tabs!!!!!!!!!!!!!!!!!
EDIT: WTF does it do when u use < pre > (one word)?!?!?!? - mandel15, on 10/11/2007, -0/+1@dgendreau
No is not. You have to define either DEBUG and use it as I did or NDEBUG to get rid of assert otherwise it goes to the final release, the compiler won't do that for you... I prefer to use DEBUG because you can use it for other code beside assertions. - dgendreau, on 10/11/2007, -0/+1@gyrotech,
Hungarian doesnt bother me to a point, but inconsistency would drive me nuts and did until I found a decent refactoring plugin for Visual Studio. - afx1, on 10/11/2007, -1/+2do these tips apply to lolcode as well? im moving away from that C++ dinosaur and into the future of programming
- Metasquares, on 10/11/2007, -1/+2Sometimes comments are useful for describing how code segments fit into the "bigger picture" of the program (or the method they're in, or whatever...). Comments may also be used to communicate information about the code *itself*, such as:
//FIXME: This is O(n^2), but there should be a way to do it in O(n) time.
Comments are still useful in these circumstances even if the code is "self-documenting".
We should try to make code as readable as possible. Both comments and descriptive coding have parts to play in this role. - superyorch, on 10/11/2007, -1/+2I have just forwarded both the link and your summary (thanks) to my developing team. I cannot stress enough the importance of proper commenting the code and this is just the right piece to illustrate my logic in requesting them to do it.
- chingy1788, on 10/11/2007, -0/+1Thats pretty much what Uni Comp courses has been teaching me
Use Comments wisely, don't comment on things that are obvious
e.g.
//Incrementing X
x++;
Don't use "Magic Numbers", instead #define them or declare them as static final variables in java
e.g.
for (i = 0; i < 10; i++), instead use
#define MAX_NUM_TREES 10
for (i = 0; i < MAX_NUM_TREES; i++)
Use meaning full variable and Function names
e.g.
instead of having
int F (Tree x)
have
int calculateTreeValue (Tree tree)
Use asserts as much as possible
e.g.
int calculateTreeValue (Tree tree) {
assert (tree != null);
}
Put in some white space, don't be afraid to use the Enter/Return key, use indents
don't over use em though - Magnimac, on 10/11/2007, -0/+1I am not much good with C++, I use more Java and Visual basic. I would like to mention that much of what's in the article here is good advice for programming in any language. I would also like to thank the submitter and all of you who have added to this article by way of thoughtful comments and questions. Review doesn't hurt, and good coding habits can be hard to achieve for even the best programmers.
- uarka, on 10/11/2007, -0/+0I believe pascal uses (* and *) much like C uses /* and */
- Magnimac, on 10/11/2007, -0/+0I don't remember who said it, or even the quote with 100% accuracy,but "There have been many irreplaceable men. The graveyards are full of them." seems apt here.
- time4tea, on 10/11/2007, -0/+0the article was complete rubbish.
inaccurate, outdated, outmoded, obvious
just cos you can blog any old stream of consciousness crap doesn't mean you should.
hungarian notation? -
Show 51 - 77 of 77 discussions



What is Digg?
Check out the new & improved