Jump to content
  • Advertisement
Sign in to follow this  
ApochPiQ

Opinion: fully bracing branching instructions in C-style languages

This topic is 4730 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Lately I've been seeing a lot of discussion on various sites, blogs, wikis, and what have you about fully bracing all braching instructions (with references to C-style languages that have bracing, or analogous optional-bracing schemes in other languages). Generally, this is the classic example given in the argument for full bracing:
if(some_condition)
   do_some_action();
Of course this appears in various forms for different branching instructions (i.e. all loops and conditionals). The argument goes that some programmer might come along in the future and need to do two things when the condition is true:
if(some_condition)
   do_some_action();
   do_some_more_actions();
He then "forgets" to add full bracing to the conditional. Oops! do_some_more_actions() is now unconditional, and will always execute. This is obviously a problem - right? Personally, I don't think so. I think this argument is a straw-man and frankly rather laughable. First of all, if you have any decent indentation standards whatsoever, it should be immediately obvious to anyone reading the code that there needs to be full bracing around a multi-line conditional block. Someone with any appreciable experience in C-style languages will immediately see that something is "wrong" with the code, simply because of the indentation and lack of bracing. Secondly, I highly doubt anyone actually forgets to do this, unless they are extremely sleep deprived or very new to C-style syntax. Following the first point, anyone adding do_some_more_actions() should immediately notice that the conditional is not fully braced, and add bracing to make it work as intended. I know I do this all the time, and it's second nature to me to look at branching instructions for full bracing when I modify them. It's sort of like making sure you put a semicolon at the end of every statement - this shouldn't be something we panic about people forgetting to do. Granted, the compiler won't gripe at me for not fully bracing, but IMO that makes it even more important that programmers be sure to take care of it without having to be reminded. Third, to my mind, if someone does forget to add full bracing, it's frankly their fault for not being careful when modifying code. In a lot of the discussions I've read, people seem to take the view that any bugs introduced by this sitation are the fault of the original coder, and the forgetful modifying programmer is absolved of all responsibility for their oversight. Perhaps this is just my own extrapolation, and perhaps it isn't what people are really thinking - but either way it seems pretty odd to me. If a maintenance programmer doesn't understand my singleton pattern and directly instantiates a copy of the singleton class, is it my fault for using a confusing pattern? Or is it his "fault" (although fault seems a pretty harsh word to me) for not being familiar with the pattern and not properly learning about it before modifying it? Anyways, as a final (and probably totally irrelevant) observation, I've noticed that a lot of full-bracing advocates are also proponents of the vertically-compacted brace style. The argument for that brace style almost universally seems to be that it saves vertical space; yet these same people end up wasting an entire line on a trailing brace for small conditionals just so they aren't guilty of someone else's (hypothetical) accidental omission of bracing in the future. Maybe this correlation is totally invented in my head, and it's certainly not really meaningful, but I found it rather ironic. Discuss.

Share this post


Link to post
Share on other sites
Advertisement
I mostly agree and I don't usually put braces when there is only one statement. But recently, I almost made the mistake of adding another statement without putting the braces (found the error 1 minute later). I blame it on python (which I have been using alot recently), and syntactically significant whitespace. Personally, I would find it better if python didn't such whitespace rules, however.

As for the bracing style. I always put braces on their own line within cpp files. I find it cleaner and more obvious. I only put them on the same line in header files, when coding simple accessors.


// Good
int foo()
{
return 0;
}

// Lame
int foo() {
return 0;
}



My logic is that the braces delimit code blocks, which are entities of their own, and as such, should have the same indentation. There is also a personal notion that it looks fugly to put the opening brace on the same line as the function declaration.

Share this post


Link to post
Share on other sites
Quote:
Original post by ApochPiQ
Secondly, I highly doubt anyone actually forgets to do this, unless they are extremely sleep deprived...


Hmm, what kind of hours do game programmers have to pull at crunch time?

'Nuff said [lol]

I actually agree that the use of full bracing for the purpouse of preventing such an accident is misguided, I've never run into that problem and I constantly program sleep deprived :-). That said, I usually put the single statement on the same line as the if (or full brace on occasion to help better visually seperate the branch, but that's a side effect of programming in 6pt Terminal on a 1600x1200 screen...) so it could be just my programming style that prevents it...

Just to take a snippet from some IP address parsing validation code:
		if ( !info.full ) throw bad_lexical_cast();
for ( int i = 0 ; i < 4 ; ++i ) if ( read_ip > 0xFF ) throw bad_lexical_cast();
if ( read_port > 0xFFFF ) throw bad_lexical_cast();



Max_Payne: I used to allways put opening braces on their own line. I usually still do examples in this format, but more and more I've been adopting the syntax of putting them on the above line, for screen economy. My main inconsistancy would be with empty functions and initializer lists. For functions that are either empty or consist only of initializer lists, I usually have an opening and closing brace each on their own line. Soon I belive it will only be with initializer lists.

I also consider both horisontal and vertical code economy - if a line extends much past 100 characters, I usually try to chop it up.

Then again I'm constantly fiddling with my view settings (tab width, font) and my writing style depends a lot on those settings, so I end up changing my style a lot too. Here's another snippet from my project:
	cluster::cluster( const std::string & group_name , const tcp_ip4_address & multicast_address ) {
platform = boost::shared_ptr< platform_implementation >(
new platform_implementation( group_name , multicast_address )
);
}

This is from inside a namespace. Right now I'm using 8-space tabs and 6pt Terminal for my font. I have the ending brace and semi-colon on a seperate line for the same reason my ending curly brace is on it's own line - to help indicate the end of a block( long line, function, class, namespace, etc ).

[Edited by - MaulingMonkey on June 10, 2005 11:51:50 AM]

Share this post


Link to post
Share on other sites
Apoch,

Within my department we use the braces for all conditional, looping, branching, etc...statements. We do this primarily for consistency, but I can definately see the argument of "people forgetting." As you pointed out, the compiler wont complain if you put the additional lines without adding the braces, however it will certainly complain about a missing semicolon.

As well, its relatively rare, except in the situation of simple return statements that no one will ever come along and add new lines to the conditional. At least its not something you can usually count on. So if there's a strong likelyhood that someone will need to add them at a later date, and that some feel the left-aligned braces on all branching statements improves readability, why not just add them in the first place?

Finally, your post seemed largely geared towards who's fault it is if the braces are later "forgotten". You appeared to have the attitude of "if I dont put braces on my statements, someone else comes along and doesnt add them, its their fault not mine." Although this is technically true, I can assure you your producer will not see it that way. Your producer will see it as the 30 minutes to 2 hours wasted on an accidental bug that could have been avoided. Will they "blame" it on who left off the braces, possibly, but either way you can be sure its 30 minutes that no one can afford to lose.

Ultimately, alignment and usage of braces is something particular to each team. Some people are happier about certain styles than others and I'm certain a holy war could easily be started over the persecution of the braces. =) In the end, the only thing that really matters is consistency. As long as everyone on a team uses the same convention, the code will be easier to read, interpret, and expound upon.

Share this post


Link to post
Share on other sites
One scary thing that can happen, which can introduce some very difficult to find bugs is something like:


if(!ret)
assert(!"DANG!");

importantUpdate();



As the assert() will be removed in a RELEASE build the importantUpdate() will end up as part of the if condition. The program will thus behave wrong in RELEASE build, which makes debugging extremely difficult. This goes for any DEBUG only functions/macros.

Share this post


Link to post
Share on other sites
All assertions should be made at the very beggining of the function, since they define the necessary conditions for the function to run properly...

Share this post


Link to post
Share on other sites
Puppet,

Good observation! I had forgotten that as well. One more reason why braces can add a bit of safety.

Share this post


Link to post
Share on other sites
One other thing to consider, where appropriate, is the use of macros. For example:


#define DO_STUFF(x) ++x; --x;

if(condition)
DO_STUFF(x);




x is only incremented when condition is true, but it is ALWAYS decremented. Maybe you don't use macros in your code, but some library might and that makes it even easier to forget since you're not used to it.

I also use the single line if statements. I'm just showing that it is a reasonable argument. The OPs example is the obvious case that's not very like, but I did see the above in real code.

Edit: This is basically a generalization of what Puppet said.

tj963

Share this post


Link to post
Share on other sites
Quote:
Original post by Puppet
One scary thing that can happen, which can introduce some very difficult to find bugs is something like:

*** Source Snippet Removed ***

As the assert() will be removed in a RELEASE build the importantUpdate() will end up as part of the if condition. The program will thus behave wrong in RELEASE build, which makes debugging extremely difficult. This goes for any DEBUG only functions/macros.

...no it won't (unless you have a truly whacky assert in your compiler). Asside from that, it's a pretty bad example because the code is horible in the first place (as is tj963's macro example).

The assert should preprocess to an empty statement, not a non-existant statement. You just try putting a semicolon after an conditional or loop (like this):
if(foo); while(bar);

In any case - if it looks clear enough, then there's nothing wrong with not bracketing an "if" statement (and less-often, loop statements). As long as you indent nicely. Not brackting can often make code clearer to read.

A lot of the examples of why brackets should always be used are terribly contrived. Or of times when they should be used (even by a not-always-bracketer).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!