views:

1035

answers:

21

What guidelines do you follow to improve the general quality of your code? Many people have rules about how to write C++ code that (supposedly) make it harder to make mistakes. I've seen people insist that every if statement is followed by a brace block ({...}).

I'm interested in what guidelines other people follow, and the reasons behind them. I'm also interested in guidelines that you think are rubbish, but are commonly held. Can anyone suggest a few?

To get the ball rolling, I'll mention a few to start with:

  • Always use braces after every if / else statement (mentioned above). The rationale behind this is that it's not always easy to tell if a single statement is actually one statement, or a pre-processor macro that expands tomore than one statement, so this code would break:
    // top of file:
    #define statement doSomething(); doSomethingElse

    // in implementation:
    if (somecondition)
        doSomething();

but if you use braces then it will work as expected.

  • Use preprocessor macros for conditional compilation ONLY. preprocessor macros can cause all sorts of hell, since they don't collow C++ scoping rules. I've run aground many times due to preprocessor macros with common names in header files. If you're not carefull you can cause all sorts of havock!

now over to you:

A: 

make sure you indent properly

DShook
+7  A: 
  • Use and enforce a common coding style and guidelines. Rationale: Every developer on the team or in the firm is able to read the code without distractions that may occur due to different brace styles or similar.
  • Regularly do a full rebuild of your entire source base (i.e. do daily builds or builds after each checkin) and report any errors! Rationale: The source is almost always in a usable state, and problems are detected shortly after they are "implemented", where problem solving is cheap.
MP24
+8  A: 

A few of my personal favorites:

Strive to write code that is const correct. You will enlist the compiler to help weed out easy to fix but sometimes painful bugs. Your code will also tell a story of what you had in mind at the time you wrote it -- valuable for newcomers or maintainers once you're gone.

Get out of the memory management business. Learn to use smart pointers: std::auto_ptr, std::tr1::shared_ptr (or boost::shared_ptr) and boost::scoped_ptr. Learn the differences between them and when to use one vs. another.

You're probably going to be using the Standard Template Library. Read the Josuttis book. Don't just stop after the first few chapters on containers thinking that you know the STL. Push through to the good stuff: algorithms and function objects.

David Joyner
+3  A: 

In if statements put the constant on the left i.e.

if( 12 == var )

not

if( var == 12 )

Beacause if you miss typing a '=' then it becomes assignment. In the top version the compiler says this isn't possible, in the latter it runs and the if is always true.

I use braces for if's whenever they are not on the same line.

if( a == b ) something();
if( b == d )
{
    bigLongStringOfStuffThatWontFitOnASingleLineNeatly();
}

Open and close braces always get their own lines. But that is of course personal convention.

Brian Paden
I agree that putting the constant on the left guards against a missing = sign ... but I've never been able to adopt it. Code just reads more naturally the other way around. Fortunately most compilers have a setting to warn about "if (a=b)" constructs.
Rob Walker
This is one of the reasons I like VB.Net. If statements don't accept assignments, and you can just use the = sign for assignment and testing for equality. It makes some code a little more verbose, but means that a lot of these bugs just can't happen.
Kibbee
+1  A: 

In a similar vein you might find some useful suggestions here: How do you make wrong code look wrong? What patterns do you use to avoid semantic errors?

Sam Hasler
+1  A: 
  • Use tabs for indentations, but align data with spaces This means people can decide how much to indent by changing the tab size, but also that things stay aligned (eg you might want all the '=' in a vertical line when assign values to a struct)

  • Allways use constants or inline functions instead of macros where posible

  • Never use 'using' in header files, because everything that includes that heafer will also be affected, even if the person includeing your header doesn't want all of std (for example) in their global namespace.

  • If something is longer than about 80 columes, break it up into multiple lines eg

    if(SomeVeryLongVaribleName != LongFunction(AnotherVarible, AString) &&
       BigVaribleIsValid(SomeVeryLongVaribleName))
    {
        DoSomething();
    }
    
  • Only overload operators to make them do what the user expects, eg overloading the + and - operators for a 2dVector is fine

  • Always comment your code, even if its just to say what the next block is doing (eg "delete all textures that are not needed for this level"). Someone may need to work with it later, posibly after you have left and they don't want to find 1000's of lines of code with no comments to indicate whats doing what.

Fire Lancer
+4  A: 
  1. Delete unnecessary code.

That is all.

Shog9
...Then I get compiler error: *unnecessaryFunction()* undefined.
Camilo Martin
+3  A: 
  1. Use consistent formatting.
  2. When working on legacy code employ the existing style of formatting, esp. brace style.
  3. Get a copy of Scott Meyer's book Effective C++
  4. Get a copy of Steve MConnell's book Code Complete.
Rob Wells
+4  A: 

Only comment when it's only necessary to explain what the code is doing, where reading the code couldn't tell you the same.

Don't comment out code that you aren't using any more. If you want to recover old code, use your source control system. Commenting out code just makes things look messy, and makes your comments that actually are important fade into the background mess of commented code.

Kibbee
+1  A: 
  1. setup coding convention and make everyone involved follow the convention (you wouldn't want reading code that require you to figure out where is the next statement/expression because it is not indented properly)
  2. constantly refactoring your code (get a copy of Refactoring, by Martin Fowler, pros and cons are detailed in the book)
  3. write loosely coupled code (avoid writing comment by writing self-explanatory code, loosely coupled code tends to be easier to manage/adapt to change)
  4. if possible, unit test your code (or if you are macho enough, TDD.)
  5. release early, release often
  6. avoid premature optimization (profiling helps in optimizing)
Jeffrey04
+7  A: 

Turn on all the warnings you can stand in your compiler (gcc: -Wall is a good start but doesn't include everything so check the docs), and make them errors so you have to fix them (gcc: -Werror).

Greg Hewgill
A: 

Hmm - I probably should have been a bit more specific.

I'm not so much looking for advice for myself - I'm writing a static code analysis tool (the current commercial offerings just aren't good enough for what I want), and I'm looking for ideas for plugins to highlight possible errors in the code.

Several people have mentioned things like const correctness and using smart pointers - that's the kind of think I can check for. Checking for indentation and commenting is a bit harder to do (from a programming point of view anyway).

Thomi
Thomi, how about Singleton detection: http://code.google.com/p/google-singleton-detector/
David Joyner
+3  A: 

There is also a nice C++ Style Guide used internally by Google, which includes most of the rules mentioned here.

macbirdie
+5  A: 

Google's style guide, mentioned in one of these answers, is pretty solid. There's some pointless stuff in it, but it's more good than bad.

Sutter and Alexandrescu wrote a decent book on this subject, called C++ Coding Standards.

Here's some general tips from lil' ole me:

  1. Your indentation and bracketing style are both wrong. So are everyone else's. So follow the project's standards for this. Swallow your pride and setup your editor so that everything is as consistent as possible with the rest of the codebase. It's really really annoying having to read code that's indented inconsistently. That said, bracketing and indenting have nothing whatsoever to do with "improving your code." It's more about improving your ability to work with others.

  2. Comment well. This is extremely subjective, but in general it's always good to write comments about why code works the way it does, rather than explaining what it does. Of course for complex code it's also good for programmers who may not be familiar with the algorithm or code to have an idea of what it's doing as well. Links to descriptions of the algorithms employed are very welcome.

  3. Express logic in as straightforward a manner as possible. Ironically suggestions like "put constants on the left side of comparisons" have gone wrong here, I think. They're very popular, but for English speakers, they often break the logical flow of the program to those reading. If you can't trust yourself (or your compiler) to write equality compares correctly, then by all means use tricks like this. But you're sacrificing clarity when you do it. Also falling under this category are things like ... "Does my logic have 3 levels of indentation? Could it be simpler?" and rolling similar code into functions. Maybe even splitting up functions. It takes experience to write code that elegantly expresses the underlying logic, but it's worth working at it.

Those were pretty general. For specific tips I can't do a much better job than Sutter and Alexandrescu.

I don't do C++, but aren't there settings for modern IDEs to enforce indentation styles, or add-ins that accomplish such code-beautifying?
Camilo Martin
+1  A: 

Where you can, use pre-increment instead of post-increment.

Ian Hickman
+2  A: 

Start to write a lot of comments -- but use that as an opportunity to refactor the code so that it's self explanatory.

ie:

for(int i=0; i<=arr.length; i++) {
  arr[i].conf() //confirm that every username doesn't contain invalid characters
}

Should've been something more like

for(int i=0; i<=activeusers.length; i++) {
  activeusers[i].UsernameStripInvalidChars()
}
Dave
+1  A: 

I use PC-Lint on my C++ projects and especially like how it references existing publications such as the MISRA guidelines or Scott Meyers' "Effective C++" and "More Effective C++". Even if you are planning on writing very detailed justifications for each rule your static analysis tool checks, it is a good idea to point to established publications that your user trusts.

Trent
+1  A: 

Here is the most important piece of advice I was given by a C++ guru, and it helped me in a few critical occasions to find bugs in my code:

  • Use const methods when a method is not supposed to modify the object.
  • Use const references and pointers in parameters when the object is not supposed to modify the object.

With these 2 rules, the compiler will tell you for free where in your code the logic is flawed!

Stacker
A: 

Smart pointers have a nice way of indicating ownership very clearly. If you're a class or a function:

  • if you get a raw pointer, you don't own anything. You're allowed to use the pointee, courtesy of your caller, who guarantees that the pointee will stay alive longer than you.
  • if you get a weak_ptr, you don't own the pointee, and on top of that the pointee can disappear at any time.
  • if you get a shared_ptr, you own the object along with others, so you don't need to worry. Less stress, but also less control.
  • if you get an auto_ptr, you are the sole owner of the object. It's yours, you're the king. You have the power to destroy that object, or give it to someone else (thereby loosing ownership).

I find the case for auto_ptr particularly strong: in a design, if I see an auto_ptr, I immediately know that that object is going to "wander" from one part of the system to the other.

This is at least the logic I use on my pet project. I'm not sure how many variations there can be on the topic, but until now this ruleset has served me well.

Carl Seleborg
+1  A: 

Also, for some good techniques you might follow Google's blog "Testing on the Toilet".

Marcin Gil
+1  A: 

Look at it six months later

DarenW