不要使用裸露的if语句
对于C、PHP、Java和Javascript程序员来说,裸露的if语句是代码地雷。
Nick Galbreath-三月 23, 2018
对于许多基于C语法风格的编程语言来说,if语句的主体是由大括号限定的。
if (foo == 1) {
delete_everything();
}
然而,在Javascript、Java、PHP、C和C++、Java、PHP中,允许 "裸 "if语句。这些语句只有一个主体,不使用大括号。
if (foo == 1) delete_everything();
if (foo == 1)
delete_everything();
还有一些其他形式的裸语句,如裸for-loops,但这是最常见的。
有两个原因不能使用裸露的if语句。首先,它们会造成不理想的差异。第二,它们会引入危险的逻辑变化。
差异不友好
现代编程是一项团队运动,随着时间的推移,一个程序会通过一系列的小改动(diffs)而被改变。这些差异经常被扫描,并根据它们来决定是否进行全面审查。因此,我们真的希望拉动请求、提交和差异尽可能的小,尽可能的有针对性,没有很多噪音。通常情况下,if语句的主体需要扩展,或者需要添加调试。让我们看看赤裸裸的例子与之相比的差异。
if (foo == 1) {
DEBUG("foo is 1)";
delete_everything();
}
第一个结果是完全重写了这一行。
< if (foo == 1) delete_everything();
---
> if (foo == 1) {
> DEBUG("foo is 1)";
> delete_everything();
> }
第二种形式更糟糕,因为它的结果是更混乱的部分重写。
1c1,2
< if (foo == 1)
---
> if (foo == 1) {
> DEBUG("foo is 1)";
2a4
> }
如果你使用正常的、多行的、带括号的格式,diff就变成了良性的。
> DEBUG("foo is 1");
像这样的单一改动可能不是什么大问题,但往往会在许多地方增加调试。用赤裸裸的if语句,增加微不足道的调试语句,使简单的diff变成了多页的。
意外的逻辑变化
前面的例子假设程序员做了正确的事情,把一个裸露的if语句转换成有大括号的语句。但如果他们只是天真地添加了调试语句呢?
if (foo == 1)
DEBUG("foo is 1)";
delete_everything();
差异仍然很简单。
> DEBUG("foo is 1");
但是逻辑却发生了巨大的变化,因为新的版本实际上是。
if (foo == 1)
DEBUG("foo is 1)";
delete_everything();
oops。
这种情况也可以反过来发生,快速注释掉一行也会引发逻辑变化。
if (foo == 1)
// delete_everything();
copy_files();
总结
如果你认为这是一个虚构的问题,我本人也被这个问题所困扰,其他人也有。阅读这个主题的stackexchange 线程,你几乎可以看到未来的事故正在等待发生,"如果别人搞砸了就不是我的问题 "的态度。
有趣的是,三个较新和最流行的语言golang、rust和swift都不允许裸露的if语句。他们产生的混乱的差异和不安全的逻辑变化无疑是其中的一些原因。如果你使用的是一种比较传统的语言,请在你的风格指南中禁止裸露的if语句,并加以执行。