views:

687

answers:

10

I am new to programming, and am wondering if there is a correct way to order your control structure logic.

It seems more natural to check for the most likely case first, but I have the feeling that some control structures won't work unless they check everything that's false to arrive at something that's true (logical deduction?)

It would be hard to adapt to this 'negative' view, I prefer a more positive outlook, presuming everything is true :)

A: 

Either / Or. I generally use the 'negative' approach though.

if (!something) {

}

ZCHudson
+3  A: 

Generally, I'd check the unexpected items first, which forces me to deal with exceptional flow of the programme.

That way, I can throw exceptions/abort operations before I start "setting up" for the normal programme flow.

biozinc
also often the shortest - which makes it easier to read the structure:if(condition) {...short...} else {...long...}
Draemon
+6  A: 

There are things to consider in addition to the value of the condition statement. For example, if the blocks of code are significantly different in size, you may want to put the small block first so that it is easier to see. (If the larger block is really large, it may need to be refactored, or perhaps pulled out into a separate method.)

if( condition is true ) {
    do something small;
} else { 
    do something;
    and something else; 
    . . .
    and the 20th something;
}

Within the condition, yes, there are some languages that will stop evaluating an expression once one part of it is false. This is important to remember if you include some sort of is-defined logic in your code: if your language evaluates the entire expression, you should do this:

if( variable is defined ) {
    if( variable == value ) {
        ...
    }
}

rather than this:

if( (variable is defined) && (variable == value) ) {
     ...
}

I don't think there is a "correct" way to design your conditions. If you are working for a company that has coding standards, you should check to see if that is included in the standards. (The last place I worked had a reasonable number of standards defined, but did not specify how to write conditional logic.)

Dave DuPlantis
+13  A: 

There is an excellent discussion of just this topic in McConnell's Code Complete. It's a book that I highly recommend. Anyway the relevant discussion is on pages 706-708 of the first edition or pg. 749-750 of second edition (thanks plinth). From that book:

Arrange tests so that the one that's fastest and most likely to be true is performed first. It should be easy to drop through the normal case, and if there are inefficiencies, they should be in processing the exceptions.

Onorio Catenacci
Totally agreed, put the one that will be executed most of the time on the top so branching is minimal.
chakrit
p749-750 in 2nd edition
plinth
@chakrit: compilers can (and do) reorder the blocks, so being on top is no guarantee of less branches. On gcc, see the documentation of __builtin_expect which you can use to tell it which result is more likely.
CesarB
@plinth, thanks so much for that. I've edited my answer to add that information.
Onorio Catenacci
Bought Code Complete today!
meleyal
@wdm, a very wise investment.
Onorio Catenacci
+2  A: 

I aim to structure my conditions in a way to minimize the amount of information the reader has to take in. Sometimes it is easier to test for the negative to prove the positive :

An example - the test to see if a period of 2 dates intersects with another period of 2 dates is easier to write as test of no intersection of 2 periods

Tom Carter
+1  A: 

If it's a simple yes or error question, then I usually structure things so that the error-handling branch is the else clause. If it's a yes or no question (ie neither branch is an error), it's purely a judgment call on what feels more natural. If there are a lot of tests which must be made before the heart of the code can execute, I usually try to structure things so that the negative tests come first and somehow skip the code that follows (return from the function, break or continue from a loop).

Sol
+2  A: 
mfx
Frankly I disagree with a lot of this. The assertion checks up front, generally yes. But cluttering up your code with lots of nested if statements just to avoid having a compound logical condition seems to lessen readability, IMHO.
tvanfosson
@tvanfosson, I agree. Deeply nested if statements can be extremely difficult to read and/or decipher--which means that a maintenance programmer is more likely to accidentally modify the test the wrong way.
Onorio Catenacci
@tvanfosson: yes, conditional nesting should not exceed depth 2 or 3.
mfx
A: 

This is a little out of the scope of the question, but generally you also want your methods to fail fast. For this reason I tend to do all of my argument validation at the top of the method, even if I'm not going to use the argument until later in the code. This hurts readability, but only in the case where the method is really long (have to scroll off the screen to see it). Of course, that's a code smell in itself and tends to get refactored out.

On the other hand, if the check isn't simple and I'll be passing it off to another method that is just going to check it anyway, I won't repeat the code to check in the current method. As with most things there is a balance.

tvanfosson
A: 

(Context: Java)

READABILITY1: Condition that resolves to a smaller block of code goes first

if (condition) {
  smallBlock();
} else {
  bigBlockStart();
  ........
  bigBlockEnd();
}

READABILITY2: Positive assertion goes first, as it's easier not to notice a negation sign

MAKING SENSE: Assert all the pre-conditions for a method using Assert.blabla() and use conditionals only for what the method does.