Sign in to follow this  
ApochPiQ

Opinion: fully bracing branching instructions in C-style languages

Recommended Posts

ApochPiQ    23064
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
Max_Payne    757
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
MaulingMonkey    1730
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[i] > 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
JWalsh    498
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
Puppet    181
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
Max_Payne    757
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
JWalsh    498
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
tj963    234
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
Andrew Russell    1394
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
Genjix    100
if my else blocks on my if code have braces or vice versa I usually put braces on the one liner as well for consistency, but otherwise its just moot.

Share this post


Link to post
Share on other sites
Aldacron    4544
For me, I don't care so much about forgetting to add the braces later, it's the act of adding them that I hate. It's a couple of extra keypresses to get everything formatted right, which slows me down. So I often add them the first time and it's done.

Share this post


Link to post
Share on other sites
ApochPiQ    23064
Quote:
Original post by jwalsh
[snip]




Consistency is a fair point. It's certainly easier to work with code where you don't have to constantly switch mental brace-interpretation gears to read different blocks. Especially in team development I recognize the benefits of this; in my current game development project we have a pretty rigorous set of conventions, but bracing style is not one of them. Every time of us has to work on someone else's code, we whine at them later about their bracing style [wink] Mainly though this seems to be little more than a personal, subjective issue, and everyone is allowed to write code in their preferred bracing style when they are working on their own large bits of code. We usually consider it proper etiquette to use someone else's brace style temporarily when tweaking their code, which helps alleviate confusion. In general I've just never experienced it as a genuine practical issue, and mostly just a matter of something to bitch at each other about over the proverbial water cooler.


I guess my focus on "finding fault" is motivated largely by the very issue you mentioned with the management. I hate getting blamed for things I didn't do, even though it goes on an awful lot in any given corporate environment. Fault aside, though, I'd like to believe that in an ideal world everyone who messes with my code has at least a measure of conscious incompetence and will be sure to account for varying preferences in bracing style, particularly when it comes to full bracing. I know I do this, and although I know the world isn't perfect, I don't think it's unreasonable to at least foster this practice among developers.

I once worked with a programmer (on the predecessor to my current project) who had some kind of religious hatred of tabs. Literally every single time this individual worked in someone else's code, he would convert every tab in the file into a set of spaces. Worst of all, he was inconsistent - sometimes a tab would go to two spaces, sometimes three or four, sometimes eight. It didn't take long for the higher-ups on the project to give him a royal bitch-slapping for it, but he managed to mangle one of my modules before the madness was stopped. It was a 1200 line maze of intensely nested logic, by necessity, and it was turned into utter crap by his rampage. To this day there is a nasty remark in the module's revision history about the incident. That more than any other single thing really convinced me that programmers should always be both mindful and respectful of other people's styles - and this means handling full-bracing correctly.


I'll openly admit to slipping a couple of bugs into code over the years because of the full-bracing problem, but invariably it was either done during a time when I shouldn't have been coding anyways (5 AM) and a lot of the code in question was rewritten the next day, or it was caught immediately during unit testing. As such I just can't see it as a legitimate "problem," at least not in the way it seems to be regarded in some circles. Consistent, easier to read (which is subjective - personally I find unbraced single-line branches much cleaner looking), and certainly a reasonable precaution, sure - but this isn't the kind of thing that we need to be paranoid about.


Macros and asserts are also fair points. However, in this case, I'd argue that the real preventative lies elsewhere. Anyone who writes a multi-instruction macro and does not brace it should be kicked in the crotch (assuming appropriate gender) and then clubbed to death with a copy of [Your Programming style Bible of Choice]. Macros are the tool of Satan in any case, and anyone who is careless with them needs a good beating. Macro-based asserts fall into this category, as Andrew already covered.


Quote:
Original post by Aldacron
For me, I don't care so much about forgetting to add the braces later, it's the act of adding them that I hate. It's a couple of extra keypresses to get everything formatted right, which slows me down. So I often add them the first time and it's done.


Actually, I personally feel the exact opposite. I hate adding braces the first time because usually when I'm writing new code I'm zoned and I like to move as fast as possible. With VC++'s autoindent, it costs me literally no keystrokes to not fully brace the first time. I can almost always predict when I will need to add further statements later, though; in those cases, I will add full bracing as a preparatory step - but usually I also write TODO comments to mark out what else needs to be added at the same time. Different strokes, I guess [smile]

Share this post


Link to post
Share on other sites
ApochPiQ    23064
Quote:
Original post by Daniel Miller
Why not put it? It takes extremely little time, and can easily save you lots of headaches.


Because those kinds of arguments are never really convincing to me [wink]

As I said above, I tend to be moving fast when writing new code. I like efficiency at that point. However, when revising code, I am exclusively moving slowly and carefully, and making sure to do fine-grain testing of any changes I make. Because of that, I usually find it plenty efficient to not full-brace. I also personally find it much more aesthetically pleasing, and a lot more economical in terms of space. When you've got a function that just makes a couple dozen simple, non-nested branching instructions, it gets real long real fast to full-brace everything, especially when there is no need to - if(x) return y; trees come to mind, which are often required for state processing logic that has to check complicated expressions or functions for each conditional (which makes a switch() impractical).

My view isn't really that full bracing shouldn't be done, but rather that it should be a subjective matter of opinion for everyone concerned. If you're careful and following good testing practices, I honestly can't see a genuine practical motivation for doing it either way - which leaves it as a subjective matter.

Share this post


Link to post
Share on other sites
Andrew Russell    1394
While ApochPiQ is linking the c2.com wiki, I'll link YAGNI for the sake of Aldacron [grin] (edit: and Daniel Miller, and everyone else really)

Also - it's not as if us non-religious-bracketters religiously go around not-bracketing one-statement if's. It's a style and readability thing generally reseved only for cases the require it.

Example: For reasons of style, I have got quite a few short 2-statement "if" blocks that are on a single line (fully bracketed because the language requires it) in one of my classes. The one-line version looks much cleaner and eaiser to read than the 5 line version. Not the same thing, but the same reasoning behind it.

Share this post


Link to post
Share on other sites
Daniel Miller    218
Having brackets probably saves time, so I really don't see that arguement.

First of all, it takes less than a second to hit shift+[+enter and enter+shift+] when you are done. No time is wasted at all. When you want to go back and add something inside of the if-statement (assuming you do it correctly), you won't have to go in and place the cursor above the text, and then below it. Now, assuming that you don't add it correctly, you can easily waste 10 minutes trying to find out why.

It just seems like you want to use your style for the sake of using it; nothing is gained. If anything, it looks better, but I don't even agree with that.

Share this post


Link to post
Share on other sites
MaulingMonkey    1730
Quote:
Original post by Daniel Miller
Why not put it?


Screen economy. Less wasted screen economy = more information on screen = faster development. It may cost little to type a couple extra braces, but there's an ongoing mantinence cost, too.

As I've allready mentioned, this dosn't mean don't ever use them when un-necessary. They can make for good visual-break indications which speeds comprehension. Faster comprehension = more information throughput on screen over time = faster development. It may allow you to fit an extra line on the screen to exclude it, but there's an ongoing mantinence cost, too. If there wasn't, we'd all be using editors that auto-formatted code via wordwrap (on a character level) with no explicit newlines and minimal whitespace. That'd look something like:
#include <iostream>
using namespace std
;int main(void){cou
t<<"Hello World"<<e
ndl;return 0;}

Share this post


Link to post
Share on other sites
ApochPiQ    23064
YAGNI is an excellent point, thanks! While in some cases I've found the principle overapplied (mostly due to improper understanding of You Are Gonna Need It) it is definitely a valuable thing to keep in mind, for any programmer. [off_topic] c2 is dangerous - I can get caught up reading that wiki for hours on end [smile] [/off_topic]

I do the same thing with short if()s, by the way. In a lot of cases I'll even single-line simple accessor/modifier functions if there are a large number of them. I find the vertical compactness very useful - I much more often need to scroll past a block of accessors to get what I want than I need to actually read what an accessor does. I think this goes back to the vertical-compactness irony I mentioned in the opening post.

Share this post


Link to post
Share on other sites
Daniel Miller    218
Quote:
Original post by MaulingMonkey
Quote:
Original post by Daniel Miller
Why not put it?


Screen economy. Less wasted screen economy = more information on screen = faster development. It may cost little to type a couple extra braces, but there's an ongoing mantinence cost, too.

As I've allready mentioned, this dosn't mean don't ever use them when un-necessary. They can make for good visual-break indications which speeds comprehension. Faster comprehension = more information throughput on screen over time = faster development. It may allow you to fit an extra line on the screen to exclude it, but there's an ongoing mantinence cost, too. If there wasn't, we'd all be using editors that auto-formatted code via wordwrap (on a character level) with no explicit newlines and minimal whitespace. That'd look something like:
#include <iostream>
using namespace std
;int main(void){cou
t<<"Hello World"<<e
ndl;return 0;}


Screens are giant; I don't think that is a valid concern. Maybe in the character-mode days, but now we have plenty of room to spare. You can also view your code in full screen if space is that much of a concern.

I should note that I [edit:] DON'T really care which one I am reading, but I think it is smarter to use brackets.

Talk about an important typo...

Share this post


Link to post
Share on other sites
Telastyn    3777
I agree that many of the arguements are fairly silly as long as consistancy is maintained.

I've settled on:

if (foo){
// stuff
}

// or for short 1-liners:
if (foo){ /*stuff*/ }


because I like the consistancy of always putting the brace after the conditional. It's a little distracting to think quickly if I need the brace or not. Also, I find it much easier to add more into the condition or add an else. This is perhaps because of my IDE, which doesn't move the cursor around easily.

Wether these are really practical reasons is questionable.

Share this post


Link to post
Share on other sites
MaulingMonkey    1730
Quote:
Original post by Daniel Miller
Screens are giant; I don't think that is a valid concern. Maybe in the character-mode days, but now we have plenty of room to spare. You can also view your code in full screen if space is that much of a concern.


I use 6pt Terminal font on a 1600x1200 screen. I'm constantly tabbing between different windows and tabs, because quite often I can't fit all the information I want on the screen at a time. As such I must disagree :-).

Share this post


Link to post
Share on other sites
Replicon    306
I like the


if(blah) {
// bleh...
}


myself, but I'll use


if(blah)
{
// bleh...
}


If everyone I'm working with is doing it. When I just have one thing, I used to not put the braces, but I find that every now and then, you will want to go back to the code and add a debug statement or something, and it's really annoying to keep adding the braces, so I do it the first time around...

The one thing that I really can't stand is:


if(blah)
{
// bleh...
}


One word: UGH!

Share this post


Link to post
Share on other sites
Holy Fuzz    213
I never add the braces until I need them because I'm a chronic procrastinator and always wait until the last moment. Same goes for debugging ;-).

As for bracing style, I prefer

if(...)
{
...
...
}

over

if(...){
...
...
}

because it's easier on my eyes and my brain. Screen real estate is cheap.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this