代码之家  ›  专栏  ›  技术社区  ›  Greg D

哪个代码更可读?

  •  32
  • Greg D  · 技术社区  · 16 年前

    假设我有两种方法 bool Foo() bool Bar() . 以下哪项更具可读性?

    if(Foo())
    {
        SomeProperty = Bar();
    }
    else
    {
        SomeProperty = false;
    }
    

    SomeProperty = Foo() && Bar();
    

    一方面,我考虑短路。 && &&

    你怎么认为?是否有其他因素影响决策?比如,如果 && 表达式比屏幕上的一行长,我应该选择前者吗?


    回答后澄清:

    在答案提出的最初问题中,我应该包括一些东西。

    • Bar() 执行成本可能比 Foo() ,但这两种方法都不应该有副作用。
    • Foo() CurrentUserAllowedToDoX() Bar() 更像是,, XCanBeDone()
    21 回复  |  直到 16 年前
        1
  •  93
  •   Eric Lippert    16 年前

    我同意普遍的共识,即Foo()&&形式是合理的

    如果Bar()对它的副作用和价值都很有用,那么我的第一个选择就是重新设计Bar(),这样副作用的产生和价值的计算是分开的。

    如果出于某种原因,这是不可能的,那么我会非常喜欢原始版本。对我来说,最初的版本更清楚地强调了对Bar()的调用是语句的一部分,这对它的副作用很有用。对我来说,后一种形式强调Bar()对于它的值是有用的。

    例如,如果在

    if (NetworkAvailable())
      success = LogUserOn();
    else
      success = false;
    

    success = NetworkAvailable() && LogUserOn();
    

    我会选择前者;对我来说,忽视后者的重要副作用太容易了。

    if (NetworkAvailable())
      tryWritingToNetworkStorage = UserHasAvailableDiskQuota();
    else
      tryWritingToNetworkStorage = false;
    

    tryWritingToNetworkStorage = NetworkAvailable() && UserHasAvailableDiskQuota();
    

        2
  •  45
  •   Matt Huggins    16 年前

    假设您的语言允许,我喜欢这种速记法:

    SomeProperty = Foo() ? Bar() : false;
    
        3
  •  19
  •   noctonura    16 年前
    SomeProperty = Foo() && Bar();
    

    这更具可读性。我不明白怎么会有人坦率地选择另一个。如果&表达式长于1行,请将其拆分为2行。。。

    SomeProperty = 
       Foo() && Bar();
    
          -or-
    
    SomeProperty = Foo() && 
                   Bar();
    

    这几乎不影响可读性和对IMHO的理解。

        4
  •  13
  •   SLaks    16 年前

    例如 IsUserLoggedIn() && IsUserAdmin() 作为一名教师肯定会更好 && ,但还有一些其他组合(我想不出任何一种是即时组合)比ifs更好。

    总的来说,我建议 && .

        5
  •  9
  •   aib    16 年前

    也不我首先要重命名SomeProperty、Foo和Bar。

    IsFather = IsParent() && IsMale();
    

    if (FPUAvailable()) {
        SomeProperty = LengthyFPUOperation();
    } else {
        SomeProperty = false;
    }
    

    这里,第一种形式强调逻辑和关系。第二种方法强调短路。我永远不会用第二种形式写第一个例子。对于第二个例子,我可能更喜欢第二种形式,特别是如果我的目标是清晰的话。

    关键是,很难用SomeProperty和Foo()和Bar()来回答这个问题。有一些很好的通用答案&&对于一般情况,但我永远不会完全排除第二种形式。

        6
  •  6
  •   Jon Skeet    16 年前

    你认为人们会以何种方式误解第二种观点?你认为他们会忘记这一点吗&&当第一个条件为false时调用第二个条件会发生什么?如果是这样的话,我就不担心了——他们也会同样困惑于:

    if (x != null && x.StartsWith("foo"))
    

    我不认为很多人会把它改写成第一种形式。

        7
  •  5
  •   JaredPar    16 年前

    在条件表达式简短的情况下,正如本例一样,我发现第二种更具可读性。你在这里想做什么,一眼就清楚了。第一个例子让我花了两次时间来理解发生了什么。

        8
  •  4
  •   leppie    16 年前

        9
  •  3
  •   BenAlabaster    16 年前

    当我阅读第一篇文章时,并不是很明显SomeProperty是boolean属性,也不是Bar()返回了boolean值,直到您阅读了语句的else部分。

    我个人认为,这种方法应该是一种最佳做法: 每一行代码都应该尽可能少地引用其他代码来解释

    因为语句一要求我引用语句的else部分来插值SomeProperty和Bar()本质上都是布尔值,所以我将使用第二个。

    在第二种情况下,在一行代码中可以立即看出以下所有事实:

    • Foo()和Bar()都返回可以解释为布尔值的值。
    • 除非Foo()和Bar()都被解释为true,否则SomeProperty应该设置为false。
        10
  •  3
  •   unknown unknown    16 年前

    它更易于调试

        11
  •  1
  •   AndreyAkinshin    16 年前

    SomeProperty = Foo() && Bar() ,因为它要短得多。我认为任何一个普通的.NET程序员都应该知道如何&&-接线员工作。

        12
  •  1
  •   Konamiman    16 年前

    我会选择长版本,因为它第一眼就清楚它的作用。在第二个版本中,您必须停止几秒钟,直到您意识到&的短路行为&操作人员它是聪明的代码,但不是可读的代码。

        13
  •  1
  •   David    16 年前

    等一下。这些陈述甚至都不是等价的,是吗?我已经看过好几次了,但它们的评估结果并不一致。

    SomeProperty = foo() ? bar: false
    

    然而,撇开逻辑错误不谈,我同意其他人的看法,即较短的版本更具可读性。

    再说一次,如果我错了,并且没有逻辑错误,那么第二种方法更具可读性,因为很明显代码在做什么。

    现在我明白了。没有逻辑错误。然而,我认为这表明,对于我们这些还没有喝咖啡的人来说,更长的版本更清晰。

        14
  •  1
  •   Jeff Hornby    16 年前

    如果,正如您所指出的,Bar()有副作用,我更喜欢更明确的方式。否则,有些人可能不会意识到您打算利用短路。

    如果Bar()是自包含的,那么我会选择更简洁的方式来表达代码。

        15
  •  1
  •   vgru    16 年前

    如果第一个版本是这样的:

    if (Foo() && Bar())
    {
        SomeProperty = true;
    }
    else
    {
        SomeProperty = false;
    }
    

    if (Foo())
    {
        if (Bar())
           SomeProperty = true;
        else
           SomeProperty = false;
    }
    else
    {
        SomeProperty = false;
    }
    

    那至少是这样 一致的 . 这样的逻辑比第二种情况更难理解。

        16
  •  1
  •   please delete me please delete me    16 年前

    这样,可以在调用Foo()之前、调用Bar()之前(以及变量集)以及变量设置为false时设置断点——显然,相同的断点也可以用于捕获Foo()vs!Foo()的情况,取决于你心中的问题。

    (C#编译速度很快,因此重新排列代码通常不是什么大问题,但会分散注意力。)

        17
  •  0
  •   itsmatt    16 年前

    第一种方法向临时观察者表明,除非Foo()返回true,否则不会执行Bar()。我知道在第二个例子中,短路逻辑会阻止Bar()被调用(我自己可能也是这样写的),但第一种方法乍一看更为有意。

        18
  •  0
  •   Kena    16 年前

    短路和行为在所有语言中都不是标准的,所以如果这对我的代码很重要的话,我倾向于谨慎使用它。

    我不相信自己在一天中第五次切换语言后会立即看到短路。

    所以,如果Foo()返回false时不应该调用Boo(),我会选择版本2,如果只是作为一种防御编程技术的话。

        19
  •  0
  •   Davit Siradeghyan    16 年前

    第一种方法可读性更强,但代码行数更多,第二种更有效,无需比较,只有一行!我认为第二个更好

        20
  •  -1
  •   Gabe Moothart    16 年前

    ?: 操作人员使用 && && 模式更受欢迎,我认为它在这种情况下是合适的。

        21
  •  -3
  •   terjetyl    16 年前

    我想说,如果一个人对实际的编程语言一无所知,那么代码是可读的,因此代码类似于

    if(Foo() == true and Bar() == true)
    then
        SomeProperty = true;
    else
        SomeProperty = false;
    

    它的可读性比

    SomeProperty = Foo() && Bar();
    

    如果程序员在您不熟悉后一种语法之后接管代码,那么他将花费您编写这些额外字符所需时间的10倍。