tags:

views:

160

answers:

8

Hello All, I’ve been coding in c# for a while now and generally have a good idea about the rule of thumb for coding standards. I’ve been recently encourage by my colleges to adopt a results based approach to coding functional blocks rather than nesting blocks of logic and am seeking your advice. Below is an example of what I’m talking about, where the result of one situation is used to determine the code path rather than nesting. It’s been suggested that this approach is easier to read, especially if the result would require several layers of nesting, however I prefer to uses Curly’s Law and refactor methods and functions where nesting becomes to deep.

private void MethodOne()
    {

        bool CarryOn = false;

        // first layer
        if (ValidationRuleOne() == true)
        {
            CarryOn = true;

        } else {

            CarryOn = false;
        }

        // second layer
        if (CarryOn) 
        {
            CarryOn = ValidationRuleTwo();

        } else {

            CarryOn = false;
        }

        // third layer
        if (CarryOn)
        {
            CarryOn = ValidationRuleThree();

        } else
        {

            CarryOn = false;
        }

    }

This approach just seems wrong to me as I would suggest that the method should be rewriten as ..

        private void MethodOne()
    {



        // first layer
        if (ValidationRuleOne() == true)
        {

            // second layer
            if (ValidationRuleTwo() == true)
            {

                // third layer
                if (ValidationRuleThree() == true)
                {


                }

            }
        }

    }

If the nesting becomes too complex then I would suggest that the method/function structure needs to be rethought to group logical groups of functionality together into additional methods or functions are required?

Any thoughts greatly appreciated.

Regards,

Tim

+9  A: 
if (ValidationRuleOne() == true)
    {

        // second layer
        if (ValidationRuleTwo() == true)
        {

            // third layer
            if (ValidationRuleThree() == true)

can be:

if(ValidationRuleOne() && ValidationRuleTwo() && ValidationRuleThree())
{
...
}

in my opinion much easier to read.

and if for some reason you need each validation rule to fire:

if(ValidationRuleOne() & ValidationRuleTwo() & ValidationRuleThree())
{...} //note the & vs &&

(and you don't need to do if(validationRule() == true), since validation returns a boolean, you don't need to compare it to one in a conditional statement).

Kevin
Do this.. unless you want to write `else` code for the `if`s =)
Nayan
Or when you have code in between ValidationRuleOne() == true and ValidationRuleTwo() == true firing. So if{x == true} ..somecode.. if(y == true) .. somecode ... etc.
bastijn
+5  A: 

Any reason why you're not just returning from the else block instead of setting "CarryOn" to false?

I agree with Kevin's suggestion of using && if you don't have anything else to do... I'm assuming that in real life you have other code in the if and else blocks. If you don't you absolutely should just use &&.

Also, in terms of style:

  • Don't compare Boolean values with true or false:

    if (ValidationRuleOne() == true)
    

    should usually be

    if (ValidationRuleOne())
    
  • Name local variables in camelCase, so carryOn instead of CarryOn.

  • If a variable is going to be set in every path (as in your first if/else), don't assign it immediately... that value is going to be discarded.

Jon Skeet
Sounds right to me - have methods return a result and check the result before continuing
bigtang
I've recently got into the habbit of using "ValidationRuleOne() == false" rather than "!ValidationRuleOne()" because it some cases it's a bit more readable. But for "== true" I agree
Matt Warren
@Matt: Can't say I agree with that... I definitely find the ! prefix nicer than a comparison with `false`... but it's all personal opinion, of course.
Jon Skeet
The example shown above was simple written as an example and I added the "== true" to make it easier for people of all levels to understand that this code is result driven.
@user466015: I would expect any C# developer to understand that "== true" is unnecessary. My point is that when you're asking a question about style, it helps if the only style point worth discussing is the one you're actually interested in.
Jon Skeet
@Jon:I actually got they idea from Ayende (see http://ayende.com/Blog/archive/2008/09/30/common-issues-found-in-code-review.aspx) and it is a bit weird initially but I think there are some cases where it makes code more readable. But as you said, personal opinion and all that ;-)
Matt Warren
@Jon Skeet: agreed, I'll limit the example next time to the bare necessities.
A: 

I have experienced both, and I believe both are ok. I think, its really boils down to personal preferences and ease of use/understanding.

KMan
+2  A: 

I would prefer:

private bool IsValid()
{
    return ValidationRuleOne() && ValidationRuleTwo() && ValidationRuleThree();
}
Darin Dimitrov
Again this is not a real life example and in the majority of cases you would probably want to exit after each validation failure to ensure that your returning something relevant to the calling party, hence the structure defined at the beginning.
+6  A: 

I personally like using guard clauses.

if (!ValidationRuleOne()) 
    return;

if (!ValidationRuleTwo())
    return;

if (!ValidationRuleThree()) 
    return;
Jeremy Roberts
I won't prefer having multiple exit points, unless the code is too simple. It becomes difficult to set/dispose some object which need to be done before exiting the function. Code duplication kicks in then.
Nayan
+1. Guard clauses rock. The code you express isn't very complex, but the deep indentation of OP's plan B (or the zig zag of his plan A) makes it looks as if it is. Guard clauses make the simple *look* simple. That's a good thing.
Carl Manaster
Nayan, I agree with you, except in the case that Jeremy mentions. I like to have guard clauses at the top of my method. If you know these are guard methods, then it becomes easier to read and understand the conditions. Also, it eliminates a lot of the "if" statements later in the code making it cleaner imho.
Bryce Fischer
I tend to agree with you Jeremy, however we're prevented from using Guard clauses as were told to program such that all functions only contain one return statement. Probably causes by previous programmers miss-use of this option.
On one hand I am sorry to hear that you are restricted, but on the other hand I like coding standards, so I am torn. Since this is the case, I think that Kevin's answer is probably the way I would go. ~5 lines vs ~17 lines to do the same thing is a win, with bonus points for readability.
Jeremy Roberts
+1  A: 

Another alternative would be to use:

if (!ValidationRuleOne()) return;
// Do some work
if (!ValidationRuleTwo() || !ValidationRuleThree()) return;

// The main body

This has a couple of benefits

  • You can do additional work between checking for various validation rules
  • .. but you can still easily validate more things in a single line if you don't need additional work.
  • You avoid indenting the code far to the right (which happens with nested ifs)

The only limitation is that you may need to move this into a separate method, so that you can use return to exit the method if validation doesn't hold.

Tomas Petricek
+1  A: 

Staying in the functional world - if you can work with lambda expressions in C#, this is exactly what you can use continuations for, in your case the continuation for each validation routine would only be executed if the validation passes.

  ValidationRuleOne(() => ValidationRuleTwo(() => ValidationRuleThree()));

public void ValidationRuleOne(Action continuation)
{
  //...

 if(validationSuccessful  && continuation!=null)
    continuation();
}
BrokenGlass
+1  A: 

For the example as given, @Darin Dimitrov's solution is the best.

If there are other actions that are taken depending on the result of verification, the obvious solution is goto!

private void MethodOne() 
{ 

    bool isValid = false; 

    // first layer 
    isValid  = ValidationRuleOne();
    if (!isValid) { goto tagApplyValidationResult; }

    isValid  = ValidationRuleTwo();
    if (!isValid) { goto tagApplyValidationResult; }

    isValid  = ValidationRuleThree()

 tagApplyValidationResult:
    if (!isValid) { Whine(); }
    else          { DoTheHappyDance(); }
} 
AShelly
I thought “goto” statements went out with the ark. These statements are only really useful now if requiring an exit from a deeply nested loop. Surely a try-catch is now the appropriate manner in which to handle these situations, where given the failure of the validation you'd throw a known exception and handle that.