Do you consider this technique “BAD”?

前端 未结 28 1436
借酒劲吻你
借酒劲吻你 2021-02-02 10:57

Sometimes you need to skip execution of part of a method under certain non-critical error conditions. You can use exceptions for that, but exceptions generally are not

相关标签:
28条回答
  • 2021-02-02 11:27

    First, if you just want an answer to whether this code structure or idiom is "bad", I would think it is. However, I think this is a symptom of bad decomposition rather than whether the code you have is "good" or "bad".

    I would think much better analysis and refactoring will have to be done to be able to further address the source of the problem, rather than looking just at the code. If you can do something like:

    if (condition1(...) && condition2(...) && condition3(...) && ... && conditionN(...)) {
        // code that ought to run after all conditions
    };
    // code that ought to run whether all conditions are met or not
    

    Then I think it would be more "readable" and more idiomatic. This way, you can make functions like:

    bool conditionN(...) {
        if (!real_condition) return false;
        // code that ought to run
        return true;
    };
    

    You get the benefit of better decomposition and help from the compiler to produce the necessary short-circuitry that &&'s will bring. The compiler might even in-line the code in the functions to produce better code than if you would doing the hand-coded loop.

    0 讨论(0)
  • 2021-02-02 11:28

    To me what you are doing is bad in so many ways. The loop can be replaced by putting that code in a method.

    I personally believe that if you have to put a ! in front of your conditions then you are looking for the wrong thing. For readability make your boolean match what you are checking for. You are really checking if there is an error or some bad condition, so I would prefer:

    If (isError)
    {
       //Do whatever you need to do for the error and
       return;
    }
    
    over
    If (!isGood)
    {
      //Do something
    }
    

    So check for what you really want to check for and keep the exception checks to a minimum. Your goal should be readibility over being tricky. Think of the poor soul that is going to have to come along and maintain your code.

    One of the first things I worked on 28 years ago was a Fortran program that always needed to check if there was a graphics device available. Someone made the grand decision to call the boolean for this LNOGRAF, so if there was a graphics device available this would be false. I believe it got set this way because of a false efficiency, the check for the device returned zero if there was a graphics device. Throughout the code all the checks were to see if the graphics device was available. It was full of:

    If (.NOT. LNOGRAF)

    I don't think there was a single:

    If (LNOGRAF)

    in the program. This was used in mission planning software for B-52's and cruise missiles. It definitely taught me to name my variables for what I'm really checking for.

    0 讨论(0)
  • 2021-02-02 11:29

    I think that there is nothing basically wrong with the technique. I think that I would make sure that the bool is named something more descriptive than isGood. Although, now that I look at it, why would it not work to put all the code that is in the loop into a single if(!isGood) block? The loop only executes once.

    0 讨论(0)
  • 2021-02-02 11:29

    This is what exceptions are for. You can't continue the logic because something went wrong. Even if recovery is trivial, it is still an exception. If you have a really good reason for not using exceptions, such as when you program in a language that does not support them, then use conditional blocks, not loops.

    0 讨论(0)
  • 2021-02-02 11:30

    I think people aren't being honest here.

    If I, as your team lead, would see code like this you'd be up for a little one on one, and flagged as a potential problem for the team as that piece of code is particularly horrid.

    I say you should listen to your colleagues and rewrite it following any of the suggestions posted here.

    0 讨论(0)
  • 2021-02-02 11:31

    What you're trying to do is non-local failure recovery. This is what goto is for. Use it. (actually, this is what exception handling is for -- but if you can't use that, 'goto' or 'setjmp/longjmp' are the next best thing).

    This pattern, the if(succeeded(..)) pattern, and 'goto cleanup', all 3 are semantically and structurally equivalent. Use whichever one is most common in your code project. There's much value in consistency.

    I would caution against if(failed(..)) break; on one point in that you're producing a surprising result should you try to nest loops:

    do{
       bool isGood = true;
       .... some code
       if(!isGood)
           break;
       .... some more code
       for(....){
          if(!isGood)
              break; // <-- OOPS, this will exit the 'for' loop, which 
                     //  probably isn't what the author intended
          .... some more code
       }
    } while(false);
    ..... some other code, which has to be executed.
    

    Neither goto cleanup nor if(succeeded(..)) have this surprise, so I'd encourage using one of these two instead.

    0 讨论(0)
提交回复
热议问题