【问题标题】:How should one comment an if-else structure? [duplicate]应该如何评论 if-else 结构? [复制]
【发布时间】:2011-02-07 07:30:06
【问题描述】:

假设你有:

if(condition) {
    i = 1;
} else {
    i = 2;
}

你需要用 cmets 解释 ifelse 块。什么是最易读的方法,以便人们一眼就能轻松找到它们?

我通常这样做:

//check for condition
if(condition) {
    i = 1;
} else {
    //condition isn't met
    i = 2;
}

我觉得这还不够好,因为 cmets 位于不同的级别,所以快速浏览一下,你会选择if 评论,而else 评论看起来像是属于某种内部结构。

像这样放置它们:

if(condition) {
    //check for condition
    i = 1;
} else {
    //condition isn't met
    i = 2;
}

对我来说也不好看,因为整个结构似乎没有注释(条件可能很大并且需要多行)。

类似的东西:

//check for condition
if(condition) {
    i = 1;
//condition isn't met
} else {
    i = 2;
}

从 cmets 的角度来看,这可能是最好的样式,但作为代码结构会令人困惑。

你如何评论这样的块?

PS.我不是在问关于重构这两行代码,只是关于代码样式和注释格式。

【问题讨论】:

  • 有了所有这些文字,问题一点也不简单:-)
  • 感谢您提出这个问题,我也一直想知道。
  • 我觉得这个应该重新开——这是一个关于编码风格的问题,可以根据专业知识来回答。

标签: coding-style comments


【解决方案1】:

我根本不会在这些特殊情况下发表评论——cmets 不会为您已经清晰的代码增加任何价值。如果您有一个非常复杂且难以阅读的条件,我会考虑将其分解为一个函数(可能是inline),并拥有一个非常简洁的名称。

【讨论】:

    【解决方案2】:

    只有在代码不能自我解释的情况下,您才应该进行注释。因此,使 if 不言自明。大概是这样

    bool fooIsNotReallyGood = ....;
    
    if(fooIsNotReallyGood) {
    ...
    } else {
    ...
    }
    

    【讨论】:

    • +1 我尽力让我的代码在没有 cmets 的情况下可以理解
    • 谢谢,但这不是问题所在。
    • @serg555:你可能没有明确提出这个问题,但这就是答案。如果您在上面的示例中使用了实际的 cmets,那么很明显它完全取决于具体评论所涉及的内容。例如,外部级别的实际评论可能会解释说,当您安装了特定的图形卡时会出现错误,否则这不是问题,因此您会根据该情况采取不同的方式。内部注释可能会解释一个特别复杂的算法以及它是如何与 if 语句的特定分支相关联的。
    • 这在简单代码的理想世界中很好。但是,如果第一个块很长,则“else”块所指的内容可能不再那么清楚(在嵌套 if 的情况下也是如此)。他也可能正在清理他不想重构的其他人的代码。这是一个完全合理的问题。
    • 这是一种有用的技术,但它绝对不能消除所有情况下对 if/else cmets 的需求。
    【解决方案3】:

    //condition isn't met 似乎是无用的评论。但是在需要这样评论的情况下,我会这样做(C#):

    //check for condition
    if(condition) 
    {
        i = 1;
    } 
    //some other condition
    else 
    {
        i = 2;
    }
    

    但是,如果块只是 if-else,那么我会在 if 之前合并两个 cmets。

    对于javascript我更喜欢

    //check for condition
    if(condition) {
        i = 1;
    } else { //some other condition
        i = 2;
    }
    

    附:似乎有多少人就有多少意见:)

    【讨论】:

      【解决方案4】:

      您可以将if-else 代码提取到方法中并正确命名:

      function main() {
        checkForCondition(condition);
        conditionIsNotMet(condition);
      }
      
      function checkForCondition(boolean condition) {
        if (condition) {
          i = 1;
        }
      }
      
      function conditionIsNotMet(boolean condition) {
        if (!condition) {
          i = 2;
        }
      }
      

      在这样一个微不足道的情况下,这似乎有点过头了,但想象一下每个 if-else 分支有不止一行。

      【讨论】:

      • 大声笑,在这种情况下做这样的事情不是更好吗?如果(条件)条件IsMet();否则条件IsNotMet();
      • 这段代码有很多问题。首先,在main() 中,您的两个函数之间的“非此即彼”关系(始终只有其中一个会生效的事实)被掩盖了。您必须在多个地方查找实际语句,并且不要立即查看是否有任何副作用。您还要检查两次条件,这可能很昂贵。并且它增加了两个函数调用的开销,这可能还需要返回一些东西给main。 — 我知道答案是旧的,但我认为以某种方式支持反对票不会有什么坏处。
      【解决方案5】:

      另一种选择是:

      if(condition) { //check for condition
          i = 1;
      } else { //condition isn't met
          i = 2;
      }
      

      【讨论】:

      • 这是我喜欢的选项......除非 cmets 真的很长,否则你就完蛋了......我很沮丧并删除了 cmets,因为它看起来很丑。
      • +1 我认为的最佳解决方案。
      • 这就是我所做的。如果 cmets 很长,则在条件句上方放置一个注释块来解释整个事情。
      • 我喜欢所有 cmets 从同一个位置开始(最好在顶层)。让它们遍布整个地方对我来说更难阅读。
      • 对我来说,“检查条件”本身或作为通用占位符都没有帮助。评论必须有帮助,而不仅仅是重复代码,因此我更喜欢“评论解释条件试图确定的内容”(详情如下)
      【解决方案6】:

      变量很重要,而不是条件本身。

      if condition: # <condition dependent variable> was <predicated>
        dosomething()
      elif othercondition: # <othercondition dependent variable> <predicated>
        dootherthing()
      else: # <all variables> <not predicated>
        doelsething()
      

      【讨论】:

        【解决方案7】:

        这就是我为 if then 语句执行 cmets 的方式,尽管我通常发现它不是必需的。我喜欢将它与 if/else 保持一致,并用标签标记到同一个位置

        if ( condition )    //if above the bar
        {
            i = 0;
            k = 1;
        }
        else                //else if below
        {
            i = 1;
            k = 2;
        }
        

        【讨论】:

        • 我喜欢这种做事方式。它可能会占用更多空间,但它绝对清楚地说明了循环/if 语句所涵盖的内容。
        【解决方案8】:

        去自我评论的条件,那么额外的 cmets 是没有必要的。假设条件是达到最大贷款价值。这给了我们:

        if (maximumLoanToValueIsReached)
        {
           i=1;
        }
        else
        {
           i=2;
        }
        

        无需指定 i=2 时尚未达到最大贷款价值,因为这是不言自明的。顺便说一句,我还会将 i 重命名为更有意义的名称。

        【讨论】:

          【解决方案9】:

          如果需要注释 if else 语句,我更愿意描述使代码达到该点的情况。 尤其是在具有高圈复杂度的代码中

          if (condition) { 
          // User is taking a course at college x:
              i = 1;
          } else { 
          // User is not taking any course at college x:
              i = 2;
          }
          

          【讨论】:

          • 我喜欢这个……特别是“else”块中的注释。您的条件应该很清楚,但是根据代码的长度和复杂性(尤其是嵌套),“else”的含义可能根本不明显。
          • 例如,如果您想在 else 块中为 i = 2 加上一些注释,这将不起作用。看起来它们都适用于i = 2,或者两者都适用于else 块。
          • @aandis 您可以缩进与i = 2; 相关的评论以区分。尽管我认为在任何实际情况下,评论本身都应该毫无疑问地指出它是指条件还是第一条语句。
          • @aandis 或者对于这种情况,您可以将两个 cmets 用一行分隔。垂直空间不应该成为问题,因为应该将冗长或不清楚的方法重构为更小/更清晰的方法。
          【解决方案10】:

          没有单一的答案 - 不同的人对于什么是可读性会有不同的看法。但是,我认为 cmets 实际上应该为(否则不言自明的)代码增加价值,并且评论风格应该是一致的。

          对于不立即不言自明的情况,我处理 cmets 的方式是这样的:

            // If the condition for a local tree imbalance is met,
            // juggle the immediate nodes to re-establish the balance.
            // Otherwise, execute a global balancing pass.
            if ( somewhat muddled condition )
            {
               ...code...
            }
            else // Tree is in local balance
            {
               ... more code...
          
            } // if/else (tree locally imbalanced) 
          

          对结尾“}”的注释主要是为了给条件结尾更多的视觉重量,使阅读源代码更容易。

          【讨论】:

            【解决方案11】:

            如果代码还没有自我记录,那么我将其结构如下:

            if (someCondition) {
                // If some condition, then do stuff 1.
                doStuff1();
            }
            else {
                // Else do stuff 2.
                doStuff2();
            }
            

            但是,如果代码已经是自记录的,那也没有多大意义。如果您因为某些复杂的情况而想添加 cmets,例如:

            if (x == null || x.startsWith("foo") || x.endsWith("bar") || x.equals("baz")) {
                doStuff1();
            }
            else {
                doStuff2();
            }
            

            然后我会考虑将其重构为:

            boolean someCondition = (x == null || x.startsWith("foo") || x.endsWith("baz") || x.equals("waa");
            
            if (someCondition) {
                doStuff1();
            } else {
                doStuff2();
            }
            

            其中变量名someCondition其实概括了整个条件。例如。 usernameIsValiduserIsAllowedToLogin 左右。

            【讨论】:

            • 我也更喜欢在同一标签级别上的其他评论。我不同意不评论代码,if 语句可能像someCondition 一样简单,但在其结构内部有例如 300 行,在这种情况下不评论 else 语句将是愚蠢的,因为你需要滚动 300 行顶部还有300底..
            【解决方案12】:

            评论是非常私人的事情,并且(从早期的一些答案中可以看出)与代码一样引起争议。

            在简单的情况下,cmets 会影响代码。但假设一个更复杂的条件,我更喜欢:

            /*
            ** Comment explaining what the condition
            ** is trying to determine
            */
            if ( condition )
            {
                /*
                ** Comment explaining the implications
                ** of the condition being met
                */
                do_something();
            }
            else
            {
                /*
                ** Comment explaining the implications
                ** of the condition not being met
                */
                do_something_else();
            }
            

            无论如何,cmets 不能只是重复代码。

            【讨论】:

              猜你喜欢
              • 2013-05-27
              • 1970-01-01
              • 1970-01-01
              • 2019-08-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多