"if"语句的编码风格

6

最近我注意到一些程序员编写“if”语句时将其反过来。也就是说,在测试中,他们首先放置常量值,然后才是要测试的变量。例如,他们会这样写:

bar = foo();
if (MY_CONSTANT == bar) {
    /*  then do something */
}

对我来说,这使得代码有点难以阅读。由于我们真正讨论的是测试变量“bar”的值,而不是所有等于“MY_CONSTANT”的变量,因此我总是将变量放在前面。这是一种未明文规定的语法。
无论如何,我发现有些程序员总是按相反的顺序做。此外,我只在过去几年中注意到这一点。我已经使用C语言编程了25多年,直到大约4年前才看到这个问题。因此我的问题是:
人们为什么要这样做?如果是这样,是什么原因?这是某些语言、项目的共同标准,还是在某些大学教授?还是只有一些人试图与众不同?

@vlad_tepesch 解释了为什么这种风格出现了;但是使用它与否主要是个人观点和风格的问题。 - MaxVT
6
不应使用Yoda条件语句。它们是古老的,现代编译器会警告你已经使用了正常顺序。 - too honest for this site
1
我认为这并不是最近才出现的。大学的联系可能解释了它为什么会一直存在。教授们厌倦了一遍又一遍地处理同样的错误,而制造这种错误的学生通常不太可能听从编译器的警告。教导学生以这种方式编写代码可以节省教授们一些时间来调试学生的代码。 - John Coleman
2
@JohnColeman:在像公司这样的专业环境中,越来越多的人拒绝使用这种代码,因为编译器会在10年以上就开始警告它们。教学生使用它们是错误的方法。更简单、更符合常规实践的做法是拒绝生成带有常见警告的诊断代码。很可能教授曾经以这种方式学习过,并且一直保持着这个习惯。不幸的是,大多数教授不喜欢学习新技巧,除非它们对他们的兴趣领域确实必要。 - too honest for this site
我从未见过Yodas被拒绝。实际上,我更喜欢它们比“正常”的构造方式,因为有时会将实际条件推到我的编辑器/调试器窗口的右侧,因为这是对某个带有13个参数的系统调用结果的检查。 - Martin James
2个回答

19

这被称为“Yoda风格”(或“Yoda条件”或“Yoda符号”),应该可以防止您意外编写

if (bar = MY_CONSTANT) {
    /*  then do something */
}

自从

if (MY_CONSTANT = bar) {
    /*  then do something */
}

会触发编译错误。

这个名字来源于"星球大战"中的角色Yoda所使用的不常见的扭曲句子结构。

在我看来,使用"Yoda风格"使得代码理解更加困难,因为它违反了正常的句子结构规则。此外,代码质量检查器(或者如评论中提到的,甚至是编译器本身)应该会对这样的赋值语句进行投诉,因此(依我之见)没有什么好理由来混淆你的代码。


2
我本希望这个答案能够有更大的价值。 - HazirBot
2
顺便说一句,这是最愚蠢的原因之一,因为有能力的编译器(或者代码检查工具)会警告条件语句中的赋值操作。 - user824425
2
@Rhymoid 人们往往忽略编译器警告。这是唯一且足够的原因。顺便说一句,由于该结构完全合法,符合标准的编译器没有理由发出警告。 - Eugene Sh.
2
@EugeneSh。当你总是使用“-Wall -Werror”时,你真的不能再忽略警告了,这应该成为所有生产代码的默认设置。 - user824425
3
“应该是”和“实际上是”通常是两回事... - Eugene Sh.
显示剩余13条评论

8

以下是一个约15年前某人认为的最佳实践标准。据称它可以防止某些人在比较操作时意外赋值。

尽管当时其效果不明确,但现今这已经100%变得无意义了,因为任何值得使用的编译器都会警告分支操作符中的赋值情况。但是大量没有思考自己所用的语言或代码含义的人仍然盲目模仿这个最佳实践标准。


我经常有意地在条件语句中执行赋值操作,特别是对于布尔类型,例如 if ((myBool=SomeBoolFunc()) == true){ // do stuff }else{ // do other stuff } // 现在我可以返回/使用 myBool 而不需要显式赋值。这样可以节省两行代码,无论 bool 是 true 还是 false 都不需要显式赋值 (if true, myBool = true, else myBool = false;)。但是,从这些答案/评论中得出的共识是这被认为是不好的做法? - yano
@yano,编译器会建议在这个赋值语句周围加上括号。没什么大不了的。 - SergeyA
好的,没错,那就是另一件事了。我很确定警告已经打开了,但我从来没有看到过有警告提醒我这个问题,不过我总是确保使用括号先进行赋值,然后再进行比较。谢谢。 - yano
1
@yano 我认为这是一种不好的做法,因为它将副作用隐藏在一个条件语句中,如果条件被增强而没有提醒短路求值可能会破坏你的赋值,也可能导致错误。 - vlad_tepesch
@yano 第二点:将bool与bool常量进行比较是很尴尬的。首先,这是不合逻辑的,因为结果也是一个bool,然后应该对常量进行测试。其次,值为2也被认为是true,但如果“true”在内部被认为是1,那么您正在测试“1==2”(请注意,语言是C,它的基本形式没有“bool”类型 - 因此必须编写一个定义,依赖于整数数据类型)。 - vlad_tepesch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接