views:

1387

answers:

23

Sometimes, I feel like it is easier to check if all of the conditions are true, but then only handle the "other" situation.

I guess I sometimes feel that it is easier to know that something is valid, and assume all other cases are not valid.

For example, let's say that we only really care about when there is something wrong:

object value = GetValueFromSomeAPIOrOtherMethod();

if((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop)))
{
    // All the conditions passed, but we don't actually do anything
}
else
{
    // Do my stuff here, like error handling
}

Or should I just change that to be:

object value = GetValueFromSomeAPIOrOtherMethod();

if((value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop)))
{
    // Do my stuff here, like error handling
}

Or (which I find ugly):

object value = GetValueFromSomeAPIOrOtherMethod();

if(!((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop))))
{
    // Do my stuff here, like error handling
}
+46  A: 

Having an empty if block with statements in the else is ... just bad style. Sorry, this is one of my pet peeves. There is nothing functionally wrong with it, it just makes my eyes bleed.

Simply ! out the if statement and put your code there. IMHO it reduces the noise and makes the code more readable.

JaredPar
Negating the entire condition sometimes makes the code confusing to read.
Eric J.
Sometimes I think this makes things harder to understand
tster
I agree with Eric. That is one of the reasons I have sometimes used this method. Wrapping the whole thing in parenthesis and then applying the '!' makes it even uglier in my opinion.
SkippyFire
I don't agree guys. It is pretty simple to grok the concept of NOT
Ed Swangren
I agree with Ed, i just look at the whole statement before the negation and then i just negate the end result. I think its pretty simple, write your condition as you would and then negate it. I don't think its confusing to read at all.
Stan R.
The concept is simple to grok, but is it always easy to read? Not really.
SkippyFire
I would say it's easier to read than an empty block hanging around..
Stan R.
@Ed: If you're the guy that wrote the complex boolean condition in the first place and it's been less than a few weeks since you wrote it, should be a piece of cake. There's a reason they teach you not to not not use double negatives in English class. They are more confusing than the positively-stated case.
Eric J.
@Eric J.: then the problem is the complex boolean expression, not the use of the NOT operator. If the expression is overly complex it should be factored out into multiple boolean variables instead.
Ed Swangren
...And comparing this to English is not an appropriate comparison. Double negatives should never be used, I don't think that the same can be said about a boolean operator.
Ed Swangren
IMHO, if simply adding a ! makes a conditional difficult to read it's probably already not in it's best form. Break it down into several smaller conditionals so @Eric's answer did.
JaredPar
Comparing to English is very valid. The Junior Programmer that stumbles across this in 3 years time will do exactly that to understand what was meant in the first place. The simpler the expression, the easier the maintenance. Agree with JaredPar also, that the expression could be simplified to enhance maintainability. A negated, trivial boolean expression is not hard to read, but the one in question has 3 terms and is not trivial.
Eric J.
@Eric J.: There are other ways to deal with complex expressions than using empty else blocks. Make a boolean flag variable, name it "AllConditionsPassed", then do `if(!AllConditionsPassed)`.
Adam Bellaire
@Adam: Which is pretty much what I conclude in my answer.
Eric J.
@Eric J.: I agree, and that is why I said the same thing above :)
Ed Swangren
+1  A: 

I do it when my brain can easily wrap itself around the logic of the success but it is cumbersome to understand the logic of the failure.

I usually just put a comment "// no op" so people know it isn't a mistake.

tster
+9  A: 

Just using the else part isn't acceptable. You needn't go to the trouble of applying De-Morgan's rule, just not the whole expresssion. That is, go from if (cond) to if (!(cond)).

George Phillips
Complex negation leads to errors, errors lead to bugs, bugs lead to suffering.
Eric J.
!Eric J.: Unless you consider negation itself complex, then there is nothing complex about it. And if negation is complex, wait until you get to *binary* operators!
Adam Bellaire
+52  A: 

Though rare for me, I sometimes feel that writing in this form leads to the clearest code in some cases. Go for the form that provides the most clarity. The compiler won't care, and should generate essentially (probably exactly) the same code.

It may be clearer, though, to define a boolean variable that is assigned the condition in the if () statement, then write your code as a negation of that variable:

bool myCondition = (....);
if (!myCondition)
{
    ...
}
Eric J.
Sorry, I just don't buy that. It reads as "Okay, if this condition is true, then... do nothing. *But*, if it *isn't* true, then do this..." How is that more readable than just saying "If this condition is not true..."?
Adam Bellaire
+1 agree with creating a seperate var to store the condition but I don't agree with your statement that having an empty IF produces clear(er) code. What intent does an empty IF convey? I would assume that the code wasn't complete if I came across it.
Jared
@Jared: When I'm reading code, a negated complex boolean condition is least legible, an empty if block is more legible, and separate variable(s) to hold the evaluated condition is most legible. Looks like the community is about evenly split on the order of the first two statements. I can just speak to what I find least confusing.
Eric J.
@Eric agree on the split. I think our answers have been ping ponging for top spot for the last few hours. Haven't ever seen a split this even.
JaredPar
@JaredPar: Yep, amazing. I have never seen that either.
Eric J.
I prefer this form. Additionally when I see code that gives me a sort of uneasy feeling as this does, I ask myself, how would I unit test this. How would I build this chunk of code (or an object or method that is semantically equivalent) via something like TDD.Then I start looking for another approach.
Rick
A: 

I like the second version. It makes code more clean. Actually this is one of the things I would ask to correct during the code review.

Dev
+1  A: 

This is not a good practice. If you were using ruby you'd do:

unless condition
  do something
end

If your language doesn't allow that, instead of doing

if(a){}else{something}

do

if(!a){something}
marcgg
Well this is a VERY simplified version. I'm not a fan of wrapping multiple conditionals statements with a negation, but Eric J.'s implementation is nice.
SkippyFire
And this is why I don't like writing code in languages that don't allow you to write custom control structures. If your language doesn't support "unless", you should just be able to add it yourself, imo.
RHSeeger
And this is why I don't like reading code in languages that do allow you to write custom control structures. If my language does not support "unless," I shouldn't have to read it in someone else's code.
Brian
+26  A: 

I should preface this by saying that it's my own personal preference, but I find myself usually pulling the validation logic out of the code and into its own validate function. At that point, your code becomes much "neater" by just saying:

if(!ValidateAPIValue(value))

That, in my mind, seems a lot more concise and understandable.

Stephen Mesa
Agreed, but you were faster. :-)
Eric King
Good idea. Similar to Eric J.'s.
SkippyFire
+3  A: 

Extract your conditions, then call

if(!ConditionsMetFor(value))
{
   //Do Something
}
Eric King
+1  A: 

I find it to be unacceptable (even though I'm sure I've done it in the past) to have an empty block like that. It implies that something should be done.

I see the other questions state that it's more readable the second way. Personally, I say neither of your examples is particularly readable. The examples you provided are begging for an "IsValueValid(...)" method.

Austin Salonen
+2  A: 

Although this is not always practical, I usually prefer to change

if (complexcondition){} else {/*stuff*/}

to

if (complexcondition) continue;
/*stuff*/

(or break out with return, break, etc.). Of course if the condition is too complex, you can replace it with several conditions, all of which cause the code to break out of what it is doing. This mostly applies to validation and error-checking types of code, where you probably want to get out if something goes wrong.

Brian
+1  A: 

If I see an "if", I expect it to do something.

if(!condition)

is far more readable.

if(condition) {
  //do nothing
}
else {
  //do stuff
}

essentially reads, "If my condition is met, do nothing, otherwise do something."

If we are to read your code as prose (which good, self-documenting code should be able to be read in that fashion) that's simply too wordy and introduces more concepts than necessary to accomplish your goal. Stick with the "!".

Brandon Belvin
+7  A: 

I think it's completely unacceptable.

The only reason at all would be to avoid a single negation and pair of parentheses around the expression. I agree that the expressions in your example are horrible, but they are unacceptably convoluted to begin with! Divide the expression into parts of acceptable clarity, store those into booleans (or make methods out of them), and combine those to make your if-statement condition.

One similar design I do often use is exiting early. I don't write code like this:

if (validityCheck1)
{
    if (validityCheck2)
    {
        // Do lots and lots of things
    }
    else
    {
        // Throw some exception, return something, or do some other simple cleanup/logic (version 2)
    }
}
else
{
    // Throw some exception, return something, or do some other simple cleanup/logic. (version 1)
}

Instead I write this:

if (!validityCheck1)
{
    // Throw some exception, return false, or do some other simple logic. (version 1)
}

if (!validityCheck2)
{
    // Throw some exception, return false, or do some other simple logic. (version 2)
}

// Do lots and lots of things

This has two advantages:

  1. Only a few input cases are invalid, and they have simple handling. They should be handled immediately so we can throw them out of our mental model as soon as possible and fully concentrate on the important logic. Especially when there are multiple validity checks in nested if-statements.

  2. The block of code that handles the valid cases will usually be the largest part of the method and contain nested blocks of its own. It's a lot less cluttered if this block of code is not itself nested (possibly multiple times) in an if-statement.

So the code is more readable and easier to reason about.

Joren
TJB
+1 Also feel this is the best approach - sorry it's not getting more votes. Martin Fowler recommends it in his "Refactoring" book. One refinement - use one liners for each check i.e. if (!validityCheck1) { return false; }, etc.
Tom Bushell
+1 ifelse and else are overrated. IMHO, just using ifs with an early exit route out of the function/method/block is the easiest to read and fastest to execute.
Evan Plaice
A: 

I occasionally find myself in a related but slightly different situation:

if ( TheMainThingIsNormal () )
    ; // nothing special to do

else if ( SomethingElseIsSpecial () )   // only possible/meaningful if ! TheMainThingIsNormal ()
    DoSomethingSpecial ();

else if ( TheOtherThingIsSpecial () ) 
    DoSomethingElseSpecial ();

else // ... you see where I'm going here

// and then finish up

The only way to take out the empty block is to create more nesting:

if ( ! TheMainThingIsNormal () )
{
    if ( SomethingElseIsSpecial () )
        DoSomethingSpecial ();

    else if ( TheOtherThingIsSpecial () ) 
        DoSomethingElseSpecial ();

    else // ...
}

I'm not checking for exception or validation conditions -- I'm just taking care of special or one-off cases -- so I can't just bail out early.

XXXXX
+1  A: 

Your question is similar to my answer(simplifying the conditions) on favorite programmer ignorance pet peeve's

For languages that don't support an until construct, chaining multiple NOTs makes our eyes bleed

Which one is easier to read?

This:

while (keypress != escape_key && keypress != alt_f4_key && keypress != ctrl_w_key)

Or this:

until (keypress  == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key)

I am of the opinion that the latter is way easier to grok than the first one. The first one involves far too many NOTs and AND conditions makes the logic more sticky, it forces you to read the entire expression before you can be sure that your code is indeed correct, and it will be far more harder to read if your logic involves complex logic (entails chaining more ANDs, very sticky).

During college, De Morgan theorem is taught in our class. I really appreciate that logics can be simplified using his theorem. So for language construct that doesn't support until statement, use this:

while !(keypress  == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key)

But since C don't support parenthesis-less while/if statement, we need to add parenthesis on our DeMorgan'd code:

while (!(keypress  == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key))

And that's what could have prompted Dan C's comment that the DeMorgan'd code hurts his eyes more on my answer on favorite programmer ignorance pet peeve's

But really, the DeMorgan'd code is way easier to read than having multiple NOTS and sticky ANDs

[EDIT]

Your code (the DeMorgan'd one):

object value = GetValueFromSomeAPIOrOtherMethod();

if ( value == null || string.IsNullOrEmpty(value.Prop) 
   || !possibleValues.Contains(value.prop) )
{
    // Do my stuff here, like error handling
}

..is perfectly fine. In fact, that's what most programmers(especially from languages that don't have try/catch/finally constructs from the get-go) do to make sure that conditions are met(e.g. no using of null pointers, has proper values, etc) before continuning with the operations.

Note: I took the liberty of removing superfluous parenthesis on your code, maybe you came from Delphi/Pascal language.

Michael Buen
A: 

I always try and refactor out big conditions like this into a property or method, for readability. So this:

object value = GetValueFromSomeAPIOrOtherMethod();

if((value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop)))
{
    // Do my stuff here, like error handling
}

becomes something like this:

object value = GetValueFromSomeAPIOrOtherMethod();

if (IsValueUnacceptable(value))
{
    // Do my stuff here, like error handling
}

...

/// <summary>
/// Determines if the value is acceptable.
/// </summary>
/// <param name="value">The value to criticize.</param>
private bool IsValueUnacceptable(object value)
{
    return (value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop))
}

Now you can always reuse the method/property if needed, and you don't have to think too much in the consuming method.

Of course, IsValueUnacceptable would probably be a more specific name.

Aaron Daniels
A: 

1st:

object value = GetValueFromSomeAPIOrOtherMethod();
var isValidValue = (value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop));
if(!isValidValue)
{
    // Do my stuff here, like error handling
}

2cnd:

object value = GetValueFromSomeAPIOrOtherMethod();
if(!isValidAPIValue(value))
{
    // Do my stuff here, like error handling
}
eglasius
+1  A: 

My answer would usually be no....but i think good programming style is based on consistency.....

so if i have a lot of expressions that look like

if (condition)
{
    // do something
}
else
{
    // do something else
}

Then an occasional "empty" if block is fine e.g.

if (condition)
{ } // do nothing
else
{
    // do something else
}

The reason for this is that if your eyes sees something several times, their less likely to notice a change e.g. a tiny "!". So even though its a bad thing to do in isolation, its far likely to make someone maintaining the code in future realize that this particular if..else... is different from the rest...

The other specific scenerio where it might be acceptable is for some kind of state machine logic e.g.

if (!step1done)
{}  // do nothing, but we might decide to put something in here later
else if (!step2done)
{
    // do stuff here       
}
else if (!step3done)
{
    // do stuff here       
}

This is clearly highlighting the sequential flow of the states, the steps performed at each (even if its nothing). Id prefer it over something like...

if (step1done && !step2Done)
{
    // do stuff here       
}
if (step1done && step2done && !state3Done)
{
    // do stuff here       
}
Wilfred Verkley
A: 

Are all the expressions really the same? In languages that support short-circuiting, making the change between ands and ors can be fatal. Remember &&'s use as a guard to prevent the other conditions from even being checked.

Be careful when converting. There are more mistakes made than you would expect.

Nosredna
A: 

In these cases you may wish to abstract the validation logic into the class itself to help un-clutter your application code.

For example

class MyClass
{
   public string Prop{ get; set; }
   // ... snip ...
   public bool IsValid
   {
      bool valid = false;
      if((value != null) && 
      (!string.IsNullOrEmpty(value.Prop)) && 
      (possibleValues.Contains(value.prop)))
      {
         valid = true
      }
      return valid;
   }
   // ...snip...
}

Now your application code

MyClass = value = GetValueFromSomewhere();

if( value.IsValie == false )
{
   // Handle bad case here...
}
TJB
A: 

I'm a fan of DeMorgan's Rule which takes your ex3 and produces your ex2. An empty if block is a mental block imo. You have to stop to read the nothing that exists - then you have to wonder why.

If you have to leave comments like // This left blank on purpose; then the code isn't very self-explanatory.

SnOrfus
A: 

The style that follow to have one block empty of if-else is considered as a bad style.. for good programming practice if you dont have to write in if block you need to put (!) 'Not' in if block ..no need to write else

If(condition) //blank else //code

can be replaced as

if(!condition) //code

this is a saving of extra line of code also..

Jaswant Agarwal
+2  A: 

This is bad style, consider some very useful alternatives:

Use a guard clause style:

object value = GetValueFromSomeAPIOrOtherMethod();

if((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop)))
{
    return;
}
// do stuff here

Extract the conditional into its own method, this keeps things logical and easy to read:

bool ValueHasProperty(object value)
{
    return (value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop));
}

void SomeMethod()
{
    object value = GetValueFromSomeAPIOrOtherMethod();
    if(!ValueHasProperty(value))
    {
     // do stuff here
    }
}
Wedge
A: 

I wouldn't do this in C#. But I do it in Python, because Python has a keyword that means "don't do anything":

if primary_condition:
   pass
elif secondary_condition1:
   do_one_thing()
elif secondary_condition2:
   do_another_thing()

You could say that { } is functionally equivalent to pass, which it is. But it's not (to humans) semantically equivalent. pass means "do nothing," while to me, { } typically means "there used to be code here and now there isn't."

But in general, if I get to the point where it's even an issue whether sticking a ! in front of a condition makes it harder to read, I've got a problem. If I find myself writing code like this:

while (keypress != escape_key && keypress != alt_f4_key && keypress != ctrl_w_key)

it's pretty clear to me that what I'm actually going to want over the long term is more like this:

var activeKeys = new[] { escape_key, alt_f4_key, ctrl_w_key };
while (!activeKeys.Contains(keypress))

because that makes explicit a concept ("these keys are active") that's only implicit in the preceding code, and makes the logic "this is what you happens when an inactive key is pressed" instead of "this is what happens when a key that's not one ESC, ALT+F4 or CTRL+W is pressed."

Robert Rossney
Which is more declarative-style programming? exit when keypress == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key;OR:if (keypress != escape_key The first one is more intent-centric. Generally, it is easier to convey when things should stop, not when they still need to continue. That's why I advocate and-less and not-less conditions. AND is a very sticky operator, and reading multiple NOTs make programmers nuts, especially the maintainers.
Michael Buen
Agree with you on the "exit when" approach.
Robert Rossney