Why is it considered a bad practice to omit curly braces?
为什么每个人都告诉我写这样的代码是一种糟糕的做法?
1 2 3 4 5 6 7 | if (foo) Bar(); //or for(int i = 0 i < count; i++) Bar(i); |
我对省略大括号的最大的论点是,有时使用大括号的行数可能是使用大括号的行数的两倍。例如,这里有一些代码可以为C中的标签绘制辉光效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor))) { for (int x = 0; x <= GlowAmount; x++) { for (int y = 0; y <= GlowAmount; y++) { g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y)); } } } //versus using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor))) for (int x = 0; x <= GlowAmount; x++) for (int y = 0; y <= GlowAmount; y++) g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y)); |
您还可以获得将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | using (Graphics g = Graphics.FromImage(bmp)) { using (Brush brush = new SolidBrush(backgroundColor)) { using (Pen pen = new Pen(Color.FromArgb(penColor))) { //do lots of work } } } //versus using (Graphics g = Graphics.FromImage(bmp)) using (Brush brush = new SolidBrush(backgroundColor)) using (Pen pen = new Pen(Color.FromArgb(penColor))) { //do lots of work } |
大括号最常见的论点是关于维护编程,以及在原始if语句和预期结果之间插入代码会导致的问题:
1 2 3 | if (foo) Bar(); Biz(); |
问题:
实际上,唯一一次真正咬我的是我调试的时候,我把bar()注释掉了:
1 2 3 | if(foo) // bar(); doSomethingElse(); |
除此之外,我倾向于使用:
1 | if(foo) bar(); |
处理上述情况。
编辑谢谢澄清这个问题,我同意,我们不应该写代码的最低公分母。
阅读速度…
除了已经提到的。在这一点上,我已经习惯于用大括号和空白来解析if语句。所以我读到:
1 2 3 4 5 6 | if (condition) { DoSomething(); } DoSomethingElse(); |
比我读的快一点:
1 2 3 | if (condition) DoSomething(); DoSomethingElse(); |
如果是这样的话,我读得慢一点:
1 2 | if (condition) DoSomething(); DoSomethingElse(); |
我读得比以前慢得多:
1 2 3 | if (condition) DoSomething(); DoSomethingElse(); |
因为我忍不住又读了一遍,以防万一,我想知道作者是否打算:
1 2 3 4 5 | if (condition) { DoSomething(); DoSomethingElse(); } |
一般已经介绍过了,但是当阅读下面的内容时,我会花很长时间来研究这个问题,以确定作者的意图。我甚至可以找到原作者来证实这一点。
1 2 3 | if (condition) DoSomething(); DoSomethingElse(); |
如果它很小,就这样写:
1 | if(foo()) bar(); |
如果它足够长,可以分成两行,使用大括号。
我也曾经认为只有在真正需要的时候才使用牙套更好。但现在不是了,主要原因是,当您有大量代码时,它确实使代码更可读,并且当您有一致的支撑样式时,您可以更快地解析代码。
除了有人向if添加第二个语句外,始终使用大括号的另一个很好的原因是可能发生如下情况:
1 2 3 4 5 | if(a) if(b) c(); else d(); |
您是否注意到else子句实际上是"if(b)"的子句?你可能知道,但你会相信有人熟悉这一点吗?
所以,如果只是为了一致性,并且因为你永远不知道当其他人(总是其他人愚蠢)更改代码时会发生什么意外的事情,我总是放大括号,因为它使源代码更易读,更容易被你的大脑解析。只有对于最简单的if语句,比如在进行委托的if语句或类似switch的if语句,如果您知道该子句将永远不会被扩展,那么我将省略大括号。
我更喜欢花括号提供的清晰度。你很清楚这是什么意思,也不必去猜测是否有人只是把它们放在一边(然后引入了一个bug)。唯一一次我忽略了它们,是我把if和action放在同一行。我也不经常这样做。实际上,我更喜欢将大括号放在自己的行中引入空白,尽管从多年的K&R类C编程开始,用大括号结束行是一种我必须努力克服的实践,如果IDE不为我强制它。
1 2 3 4 5 6 | if (condition) action(); // ok by me if (condition) // normal/standard for me { action(); } |
这并不总是被认为是一种糟糕的做法。Mono项目编码指南建议如果不需要的话不要使用大括号。同样适用于GNU编码标准。我认为这是个人品味的问题,就像编码标准一样。
线路很便宜。处理器的电源很便宜。开发时间非常昂贵。
一般来说,除非我正在开发一些绝对资源/速度关键的应用程序,否则我在编写代码时总是出错
(a)任何其他开发人员都可以很容易地了解我所做的工作。
(b)评论可能需要的代码的特定部分
(c)如果出现问题,易于调试
(d)如果将来需要,则易于修改(即添加/删除代码)
从业务角度来看,代码的速度或学术优雅是这些因素的次要因素。这并不是说我开始写笨拙或丑陋的代码,但这是我的优先顺序。
在大多数情况下,通过省略大括号,对我来说,(b)、(c)和(d)更加困难(然而,注意并不是不可能的)。我想说,使用大括号与否对(a)没有影响。
我认为这是你所从事项目的指导方针和个人品味的问题。
我通常在不需要它们的时候省略它们,除了以下一些情况:
1 2 3 4 5 6 7 8 | if (something) just one statement; // i find this ugly else { // many // lines // of code } |
我更喜欢
1 2 3 4 5 6 7 8 9 10 | if (something) { just one statement; // looks better:) } else { // many // lines // of code } |
我以前也是这么想的。
直到有一天(为什么总有一天会永远改变你的生活?)我们连续24-36小时不睡觉调试生产代码,结果发现有人没有将大括号与搜索/替换更改结合起来。
就像这样。
1 2 3 | if( debugEnabled ) println("About to save 1 day of work to some very important place."); saveDayData(); |
后来的是
1 2 3 | if( debugEnabled ) // println("About to save 1 day of work to some very important place."); saveDayData(); |
结果发现系统每天生成500 MB的日志,我们被要求停止它。调试标志不够,因此搜索并替换println是正确的。
然而,当应用程序投入生产时,调试标志关闭,重要的"savedaydata"从未被调用。
编辑
现在,唯一不使用大括号的地方是if/try构造。
1 2 3 | if( object != null ) try { object.close(); } catch( ..... |
在看了一个超级明星的开发者之后。
其中一个可以咬你的例子回到了C/C++宏的过去。我知道这是一个C问题,但通常编码标准会延续下去,而没有理由首先创建标准。
如果在创建宏时不太小心,则可能导致不使用的if语句出现问题。
1 2 3 | #define BADLY_MADE_MACRO(x) function1(x); function2(x); if (myCondition) BADLY_MADE_MACRO(myValue) |
现在,别误会我的意思,我并不是说你应该总是做{}来避免C/C++中的这个问题,但是我不得不处理一些非常奇怪的错误。
我很高兴:
1 2 3 4 5 6 | foreach (Foo f in foos) foreach (Bar b in bars) if (f.Equals(b)) return true; return false; |
就个人而言,我不明白为什么
1 2 3 4 5 6 7 8 9 10 11 12 | foreach (Foo f in foos) { foreach (Bar b in bars) { if (f.Equals(b)) { return true; } } } return false; |
更具可读性。
是的,行是免费的,但是为什么我必须滚动浏览页面和页面的代码,而它可能只有一半的大小?
如果可读性或可维护性存在差异,那么,当然,将大括号放在…但在这种情况下,我看不出任何理由。
此外,我将始终为嵌套的if放置大括号,其中我嵌套了其他的if
1 2 3 4 5 | if (condition1) if (condition2) doSomething(); else (condition2) doSomethingElse(); |
VS
1 2 3 4 5 | if (condition1) if (condition2) doSomething(); else (condition2) doSomethingElse(); |
非常混乱,所以我总是这样写:
1 2 3 4 5 6 7 | if (condition1) { if (condition2) doSomething(); else (condition2) doSomethingElse(); } |
只要可能,我使用三元运算符,但从不嵌套它们。
坦率地说,我认为这是:
好的程序员会防御性地编程,坏的程序员不会。
由于上面有几个例子,以及我自己对忘记大括号相关的bug的类似体验,所以我学会了始终使用大括号的困难方法。
其他任何事情都是选择个人风格而不是安全,这显然是糟糕的编程。
乔尔甚至在让错误的代码看起来是错误的时候提到过这一点。
一旦你因为缺少大括号而被一个bug咬了一口,你就会发现缺少大括号看起来是错误的,因为你知道它是另一个bug可能发生的地方。
我同意"如果你足够聪明,让别人付钱给你写代码,你应该足够聪明,不要仅仅依靠缩进来看到代码的流动。"
然而。。。错误是可以犯的,而这是调试的痛苦…尤其是当你进来看别人的密码时。
我偶尔会使用最底层的代码(多个using语句),但除此之外,我总是使用大括号。我发现它能让代码更清晰。从缩进中可以明显看出,语句是块的一部分(因此可能是if等的一部分)。
我见过
1 2 3 | if (...) foo(); bar(); |
臭虫咬了我一口(或者更确切地说是"我和同事"——实际上我没有引入臭虫)。尽管我们当时的编码标准建议在任何地方使用大括号,但这一点仍然存在。我花了很长时间才发现——因为你看到了你想看到的。(这是大约10年前的事了。也许我现在能更快地找到它。)
当然,如果您使用"在行尾加支撑",它会减少额外的行数,但我个人还是不喜欢这种样式。(我在工作中使用它,发现它没有我想象的那么不愉快,但它还是有点不愉快。)
总是有例外,但我反对仅当大括号的形式之一时省略大括号:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 if(x == y)
for(/* loop */)
{
//200 lines
}
//rampion's example:
for(/* loop */)
{
for(/* loop */)
for(/* loop */)
{
//several lines
}
}
否则,我就没问题了。
我对我在计算机编程领域的同龄人(你们很多人)感到印象深刻,并感到羞愧,因为当你跳过单行代码块上的大括号时,潜在的错误并不会让他们望而却步。
我想这意味着我不聪明。我在这件事上犯过很多次错误。我在这件事上纠正了别人的错误。因为这个原因,我已经看到软件带有错误(RDP到一台运行vs2002的机器上,你的监视窗口字体会变得不稳定)。
如果我看看我犯的所有错误,这些错误可以通过改变编码样式来避免,那么这个列表就非常长。如果我没有在这些情况下改变我的方法,我可能永远也不会成为一个程序员。再说一次,我想我不聪明。作为补偿,我在很长一段时间内一直在使用单行块上的大括号。
也就是说,世界上有些事情已经发生了变化,使得"你应该在单行块上使用大括号"的规则今天比摩西把它带到我们这里的时候更不相关:
一些流行的语言通过让计算机读取缩进来解决这个问题,就像程序员那样(例如python)。
我的编辑器会自动为我设置格式,这样我被缩进误导的机会就大大减少了。
TDD意味着如果我引入了一个bug,因为我被一个单行块搞糊涂了,我很可能会很快发现这个bug。
重构和语言表达意味着我的代码块要短得多,单行代码块的发生频率要比以前高得多。假设,有了提取方法的无情应用,整个程序中可能只有一个行块。(我想知道那会是什么样子?)
事实上,无情地重构和省略单行块上的大括号有一个明显的好处:当你看到大括号时,你的大脑会发出一个小警报,上面写着"复杂性在这里!"当心!".想象一下如果这是一个标准:
1 2 3 4 5 6 7 8 | if (condition) Foo(); // normal, everyday code if (condition) { // something non-trivial hapening; pay attention! Foo(); Bar(); } |
我开始考虑将我的编码约定改为"单行块可能永远没有大括号"或"如果您可以将块放在与条件相同的行上,并且它都在80个字符以内,则省略大括号"。我们拭目以待。
我的哲学是,如果它使代码更可读,为什么不做呢?
显然,你必须在某个地方划一条线,比如在简洁和过度描述性的变量名之间找到快乐的媒介。但是括号确实可以避免错误,提高代码的可读性。
你可以争辩说,聪明到能成为编码员的人会聪明到足以避免阻止无括号语句的错误。但你能诚实地说你从来没有被像拼写错误这样简单的东西绊倒过吗?在查看大型项目时,这样的细节可能会让人难以抗拒。
三大公约中:
1 | if(addCurleyBraces()) bugFreeSofware.hooray(); |
还有:
1 2 | if(addCurleyBraces()) bugFreeSofware.hooray(); |
和(表示使用左大括号和右大括号的任何缩进样式):
1 2 3 | if(addCurleyBraces()) { bugFreeSofware.hooray(); } |
我更喜欢最后一个:
- 我发现如果所有的if语句都用统一的方式写的话,就更容易阅读了。
- 它可能会使软件变得更加健壮,并且没有缺陷。然而,所有现代的IDE和高级文本编辑器都有很好的自动缩进功能,我认为每个人都应该使用这些功能,只要它不会破坏注释格式或违反团队标准(在很多情况下,可以创建自定义格式方案并与团队共享)。我这里的观点是,如果正确地进行缩进,那么引入错误的风险会降低一点。
- 我更喜欢布尔表达式和语句在不同的行上执行。我喜欢为调试目的标记行。即使我使用的是一个可以标记语句并单步执行的IDE,这也是一个交互式操作,我可能会忘记从何处开始调试,或者至少需要一点时间来单步执行代码几次(因为在调试期间,每次都必须手动标记位置)。
反对使用大括号的主要论点是,它们使用了额外的行,并且需要额外的缩进。
行(几乎)是免费的,最小化代码中的行数不应该是一个目标。
压痕与支架的使用无关。在您的级联"使用"示例中,我仍然认为您应该缩进它们,即使您省略了大括号。
我非常相信编写整洁简洁的代码,但我总是使用大括号。我发现它们是快速查看特定代码行存在的范围的一种方便方法。没有歧义,它只是明确地摆在你面前。
有些人可能会说这是一种偏好,但我发现,如果程序内部一致,那么它的逻辑流程就更容易遵循,而且我不认为这样编写一个if语句是一致的;
1 2 3 4 | if(x < y) x = y; else y = x; |
另一个是这样的;
1 2 3 4 5 6 7 8 9 10 | if(x < y) { x = y; x++; } else { y = x; y++; } |
我更喜欢选择一种通用样式并坚持下去:)
使用一些个人判断。
1 2 | if (foo) bar(); |
本身就很好。除非你真的担心白痴们以后会这样做:
1 2 3 | if (foo) bar(); baz(); |
如果你不担心白痴,你很好(我不担心——如果他们不能正确地使用基本的代码语法,这是他们的问题中最小的一个)>
作为交换,它的可读性要高得多。
其余时间:
1 2 3 4 | if (foo) { bar(); baz(); } |
这是我最喜欢的。另外:
1 2 3 4 5 6 | if (foo) { bar(); baz(); } else { qux(); } |
为我工作。
垂直空间本身没有太大的相关性,可读性是。一行上的左大括号本身就停止了一个句法元素的对话,直到你的眼睛向下移动到下一行。不是我喜欢的。
其中一个主要问题是,当您有一个衬板和非一个衬板的区域时,与控制站分离(
例如:
1 2 3 4 5 6 7 8 9 10 | for (...) { for (...) for (...) { // a couple pages of code } // which for block is ending here? A good text editor will tell you, // but it's not obvious when you're reading the code } |
好吧,这是一个老生常谈的问题。我还有一些事要补充。
首先,我要说的是使用支架。它们只能帮助可读性和可读性(为您自己和他人!)除非你在写程序集,否则应该在你的优先顺序表上排在很高的位置。不可读的代码总是会导致错误。如果您发现大括号使代码占用了太多的空间,那么您的方法可能太长了。如果你做得对的话,大多数或者所有的方法都应该适合一个屏幕高度,而find(f3)是你的朋友。
现在我要补充一点:这有一个问题:
1 | if (foo) bar(); |
尝试设置一个断点,该断点仅在bar()将要运行时才会命中。在C语言中,您可以通过将光标放在代码的后半部分来实现这一点,但这并不明显,而且有点痛苦。在C++中,你根本做不到。我们在C++代码上工作的最高级开发人员坚持为此将"IF"语句分成两行。我同意他的观点。
这样做:
1 2 3 4 | if (foo) { bar(); //It is easy to put a breakpoint here, and that is useful. } |
我曾经是"必须使用大括号"的大力支持者。但是,由于采用了单元测试,我发现我的单元测试可以保护无支撑语句不受以下情况的影响:
1 2 3 | if (foo) snafu(); bar(); |
通过良好的单元测试,我可以自信地省略简单语句的大括号,以提高可读性(是的,这是主观的)。
或者,对于类似于上面的内容,我可能会将其内联,如下所示:
1 | if (foo) snafu(); |
这样,需要向条件添加bar()的开发人员更容易认识到缺少大括号,并添加它们。
减少行数并不是删除大括号的好理由。如果您的方法太大,那么应该将其重构为较小的片段或重构。这样做无疑会增加可读性,而不仅仅是去掉大括号。
为了防止带大括号的代码占用大量空间,我使用了《代码完成》一书中推荐的技术:
1 2 3 4 5 6 7 | if (...) { foo(); bar(); } else { ... } |
假设您有一些代码:
1 2 | if (foo) bar(); |
然后有人过来补充说:
1 2 3 | if (foo) snafu(); bar(); |
根据写入方式,bar();现在被无条件执行。通过包含大括号,可以防止这种意外错误。代码的编写方式应使错误难以或不可能发生。如果我正在进行代码检查,看到缺少的大括号,特别是跨多行的大括号,我将创建一个缺陷。在有理由的情况下,将其保持在一行,以便再次将发生此类错误的可能性保持在最低限度。
我总是在适当的时候省略它们,比如在第一个例子中。与必须逐行滚动和读取的代码相比,通过浏览一眼就能看到和理解的干净、简洁的代码更易于维护、调试和理解。我认为大多数程序员都会同意这一点。
如果您开始执行多个嵌套、if/else子句等操作,它很容易失控,但我认为大多数程序员应该能够知道在哪里划出界限。
我觉得这有点像
大多数时候,无论是公司还是FOSS项目,它都是根深蒂固的编码标准。
最终,其他人将需要摸索您的代码,对于每个开发人员来说,必须找出他们正在处理的代码部分的特定样式是一个主要的时间消耗。
另外,想象有人每天不止一次地在python和cish语言之间徘徊……在Python中,缩进是语言块符号的一部分,很容易犯错误,就像您引用的那样。
在更安全的方面出错-只有一个可能不需要修复的错误。
如果我所有的积木都用卷发包起来,我个人会感觉更安全。即使对于一行程序,这些都是简单的符号,可以很容易地防止错误。它使代码更具可读性,因为您清楚地看到块中的内容,以免将块体与块外部的以下语句混淆。
如果我有一个一行程序,我通常将其格式化如下:
1 | if( some_condition ) { do_some_operation; } |
如果线路过于繁琐,则使用以下方法:
1 2 3 4 | if( some_condition ) { do_some_operation; } |
他们告诉你是因为他们仍然使用古老的或通用的(不懂语言的)源代码编辑器。如果使用具有自动缩进功能的编辑器,则永远不会犯任何错误,因为使用大括号可以避免这种错误。
另一种方法是将两种方法结合在一起:
1 2 | if(foo) {DoSomething();} |
如果行被注释掉,或者在它下面添加了另一行,这就避免了任何混淆。
另外,我们使用misra-c作为编码标准,它要求像这样的所有构造在任何情况下都使用大括号。
如果你的维护程序员在应用程序中添加了逻辑,他/她可能会忘记在以后添加大括号。因此,会发生以下情况:
1 2 3 | if(foo) bar(); bar(delete); |
而不是
1 2 3 4 | if(foo) { bar(); } bar(delete); |
保罗说:
And indentation is independent of brace usage.
对于某些编码样式,这是不正确的。在我工作的地方,公司的编码标准允许我们在不严格需要大括号的情况下不使用大括号;但是,编码标准使我们缩进大括号以及大括号中的内容,因此我们最终得到如下结果:
1 2 3 4 5 6 7 | if (something) { for (i = 0; i < count; i++) { foo(); } } |
如果没有支撑,这将变成:
1 2 3 | if (something for (i = 0; i < count; i++) foo(); |
使用这种编码方式,当有深度嵌套时,再加上长变量和函数名,并且总是使用大括号,您要么从屏幕右侧获得大量代码,要么进行大量换行,这两种方式(IMO)都会使代码难以读取或调试。因为这个原因,我总是倾向于在任何时候我可以摆脱这样做的支撑。
至于将一条语句放在与if相同的行上,有些公司的编码标准(包括我们的)禁止这样做,因此它并不总是一个选项。
如果是我的选择,我将更改公司编码标准,使大括号与if、for等保持水平,并使正文中的第一行(或注释)与左大括号位于同一行,因此:
1 2 3 4 5 | if (something) { for (i = 0; i < count; i++) { foo(); } } |
我更愿意(也更愿意)一直使用大括号(甚至可以支持"总是使用大括号"规则),因为每对大括号只会添加一行额外的行,没有缩进,使得它几乎和完全没有大括号一样紧凑。
1 2 3 | if ( any ) { DoSomething(); } |
1 | if ( any ) { DoSomething(); } |
如果您认为,在一行中不可读,那么可以用两行来写:
1 2 3 4 | if ( any ) { DoSomething(); } if ( any ) { DoSomething(); } |
- 将来会有人需要改变一个语句到多个语句。没有括号的变化更大复杂的。是的,只有一点点,但是更好的预防错误。写作括号很容易,是一种便宜的方法。
我认为这一切归结为偏好和可读性。一般来说,添加大括号会使代码更易于阅读,因为实际的代码行之间有额外的空间。另外,考虑这个例子(不是故意缩进的):
1 2 3 4 5 | if (condition1) if (condition2) doSomething(); else doSomethingElse(); |
何时打电话给DoSomethingElse?当Condition1为true但Condition2为false时,还是当Condition1为false时?添加大括号可以快速解决这个可读性问题并避免混淆。
我以前也讨厌牙套。直到有一天我发现了它们的用处。我在不同的平台上工作,将应用程序从一个平台移植到另一个平台(总共工作6个)。在UNIX上,如果安装了VIM,那么可以通过按"shift+5"轻松跳转到代码块的结尾或开头。这些大多是if/else块或循环。
所以如果我在Vim上研究Rampion的问题,我会完全迷失方向,需要一段时间才能完全理解代码。
我不认为省略大括号总是一个坏习惯,但是是否应该被允许,在什么情况下必须在团队中达成一致。
我觉得这很易读:
1 2 | if (foo) bar(); |
而这个:
1 2 3 4 | if (foo) bar() else snafu(); |
如果在这些文件中添加了额外的行:
1 2 3 | if (foo) bar(); snafu(); |
这看起来都不对,有一块代码,缩进了。但没有支撑。
for循环也有类似的参数。然而,当我开始筑巢时:
1 2 3 | if (foo) if (bar) snafu() |
现在我遇到麻烦了,它看起来像一组陈述。就我个人而言,我只会跳过对一个级别的大括号的使用,只会更深入一点,我会让外部代码使用大括号:
1 2 3 4 | if (foo) { if (bar) snafu() } |
当我输入这个时,我已经看到答案从1跳到17,很明显这是一个情绪化的问题(我建议你在标签列表中添加主观因素(我的能力已经失去了这一点?).
最重要的是在团队中就是否可以接受以及如何接受它达成一致,并坚持下去。
我也喜欢更紧凑的格式。这就是为什么我总是按ctrl+k,ctrl+d在Visual Studio中重新格式化。我只希望每次按键后都能帮我做这个。
好吧,在我看来,这更像是我个人的偏好。不过,我注意到,对于可读性,最好先有再没有。我注意到使用resharper时,resharper倾向于删除它们,并对大多数if语句执行如下操作
1 2 | if(this == yes) DoSomething(); |
但是为了可读性,我总是这样做
1 2 3 4 | if(this == yes) { DoSomething(); } |
尽管"if"语句中只有一行代码的可读性并不是真正的不同,但是如果将20-30行代码放入一个if语句中,那么使用语句更容易阅读,并且在代码中留下更少的错误和错误空间。
我总是使用大括号,除了最里面的语句,假设最里面的语句是一个单行。所以我的代码看起来是:
1 2 3 4 5 6 7 8 | for (int i=0; i<10; i++) { for (int x=0; x<20; x++) { if (someBoolValue) DoThis(x,y); } } |
当然,另一个例外是使用语句进行叠加。
写作毫无意义
你什么时候能写
因为Stylecop是这么说的。
当我看到"这种风格节省空间"时,我总是很困惑。因为我很少(如果有的话)打印出代码,所以空间的增加对我来说没有明显的优势:在磁盘上保存一些字节不值得,而且我也不为屏幕上占用的空间付费。有些人觉得紧凑的代码更易读,我不认为这一点(高度主观),但作为业余艺术家和排版,我高度重视空白的使用…
我不会重复上面的参数,但我想我会补充一点,一致性:我不喜欢像这样的代码
1 2 3 4 5 6 | if (foo) { // Lot of code } else DoStuff(); |
说了这句话,有时我不穿背带裤:在警卫的条件下,当我早退时:
1 2 | if (somethingBadHappened) return; |
总的来说,我认为在重要的代码周围添加(几乎)系统的大括号可以提高可读性(代码"呼吸",不拥挤),一致性,并且可以避免一些愚蠢的错误(是的,这种错误是明显的,但编码员是人(一般来说),可能很累,新手,压力之下…)。
我为Scite制作了一个Lua宏,在代码块或当前行周围添加这些大括号,只需一次击键并正确地缩进即可:这对我来说真的是一分钱也不花。
现在,如果你选择省略这些大括号,我不会起诉你。正如其他人指出的,在编码规则中可以设置一个或另一个选项。他们各自拥有。
如果您觉得"有时"使用大括号很有用,那么应该增加大括号以保持一致。程序应该由人而不是计算机来读。我喜欢大括号,比如:
1 2 3 4 5 6 7 8 9 | if (mybool) { doMyStuff(); } else { doMyOtherStuff(); checkStuff(); } |
而不是像
1 2 3 4 5 6 7 | if (mybool) { doMyStuff(); } else { doMyOtherStuff(); checkStuff(); } |
而不是像
1 2 3 4 5 6 7 | if (mybool) doMyStuff(); else { doMyOtherStuff(); checkStuff(); } |
另一方面,如果要删除/不使用大括号保存行,则需要重构代码。
一方面,我把大括号留给了一个单独的语句。另一方面,我使用pc lint(http://www.gimpel.com/)检查所有C代码,它将if()语句后面的两行或多行缩进标记为"可疑缩进"。
顺便说一下,将单个语句放在与if()相同的行上看起来是个好主意。
这是一种更短的代码(可读性更好)与更安全的代码(不易出错)的权衡。
我的2分钱:
您是否考虑过将此选项用于单行if else语句:
1 | (!a) ? Foo() : Bar(); |
在大多数情况下我更喜欢牙套。通常情况下,您将返回到代码以添加更多的代码行,并且无论如何都必须添加它们。
关于你为什么不应该这样做,这里有很多很好的答案——我同意你不应该省略牙套。
如果你想寻找更简洁的代码,我会使用三元语句。它们提供了一定数量的明确性和紧凑性,更能抵抗事故。
如前所述,省略大括号的问题是,事实发生后可能会出错。大多数程序员都同意他们可以阅读:
1 2 | if( foo ) bar(); |
当人们来改变陈述而不注意的时候,问题就出现了。在我工作的最后一个地方,实际上有一个问题,是由于有人修改了声明或评论了一行。制定了一个编码标准,以确保类似的错误不会再次发生。
正如别人所说,编程时间是很昂贵的。就像注释代码一样,省略位通常更快,因为它们是可选的,但是易于维护的代码通常依赖于那些"可选"的东西。
最后,有些人提到现代编辑器和IDE应该自动缩进并自动显示您的范围。我的答案是不要用拐杖之类的东西。有时,您会从源存储库、远程连接甚至电子邮件中查看代码——这些都是开发的现实。您可能没有IDE或高级编辑器来显示您所做的错误。始终编写代码,这样无论您加载什么代码,都可以理解它。
afair花括号始终是一个范围,因此每次使用它们都是很好的。
不带支架:
1 2 3 4 | if(DoSomething) MyClass myClass = new MyClass(); myClass.DoAnythingElse(); |
这将编译,但很容易导致空引用。(C编译器不会编译这个,好消息!)
鉴于此:
1 2 3 4 5 6 | if(doSomething) { MyClass myClass = new MyClass(); } myClass.DoAnythingElse(); |
甚至不会编译。
与在运行时查找异常相比,在compiletime将异常缩小要好得多。