如何在代码中使用空行?


31

关于花括号放置的讨论中已经有关于空白的一些评论。

我本人倾向于在我的代码上加上空白行,以试图将“逻辑”组中的所有内容隔离开来,并希望使下一个人更容易阅读我刚刚生成的代码。

实际上,我会说我像编写代码那样构造代码:我创建一段不超过几行(绝对短于10行)的段落,并尝试使每个段落都是独立的。

例如:

  • 在一个类中,我将组合在一起的方法,同时将它们与下一组分隔为空白。
  • 如果我需要写评论,通常会在评论前放一个空白行
  • 在一种方法中,我在过程的每一步都写一个段落

总而言之,我很少有超过4/5的行聚集在一起,这意味着代码非常稀疏。

我不认为所有这些空白都是浪费的,因为我实际上使用它来构造代码(实际上是使用缩进),因此,我觉得值得这样做。

例如:

for (int i = 0; i < 10; ++i)
{
    if (i % 3 == 0) continue;

    array[i] += 2;
}

我认为这两个陈述具有明确的不同目的,因此应该分开以使其显而易见。

那么,如何在代码中实际使用(或不使用)空行呢?


6
if (i % 3 != 0) { <newline here> array[i] += 2; <newline here> },但我明白你的意思了:)
Merlyn Morgan-Graham 2010年

这些类型的问题不是建设性的。您只有很多次可以改写“是”和“否”的两个唯一答案。

1
一个更好的问题是如何以及为什么使用空白行?我以与您完全相同的方式使用空白行,并且动机相同。
Dominique McDonnell

1
@ Mark,@ takeshin:对不起,忘记了关键字中的“方式”。显然我们大家都在使用它们,我试图查看那里的人是如何使用它们的(分隔类,if / else等...),但似乎我得到了非常通用的答案:p
Matthieu M.

3
for (int i = 0; i < 10; i += 3) { <newline here> array[i] += 2; <newline here> }但我明白你的意思了:)
Berin Loritsch 2011年

Answers:


87

总是

空格对于清除可读代码至关重要。空行(或两行)有助于从视觉上分离出逻辑代码块。

例如,摘自史蒂夫·麦康奈尔(Steve McConnell)的《代码完成》第二版中有关布局和样式的章节:

当程序采用2到4个空格的缩进方案时,与没有进行缩进的程序相比,受试者在理解测试中的得分高出20%到30%。同一项研究发现,既不强调也不强调程序的逻辑结构很重要。在完全没有缩进的程序中获得最低的理解分数。在使用六空间缩进的程序中,第二低的值达到了。研究得出的结论是2到4空间的压痕是最佳的。有趣的是,实验中的许多对象都认为六空间缩进比较小的缩进更易于使用,即使得分较低。这可能是因为六个空格的缩进看起来令人愉悦。但是,不管看起来多么漂亮,六空格的缩进都变得不那么可读。这是美观和可读性之间冲突的一个例子。


12
我听到有人说“但是您应该提取方法!”。一段是针对没有足够理由提取方法的情况。
Frank Shearar

1
可以很容易地进行实验,看看是否有垂直空格更好。取一个您不知道的源文件,删除所有空白行,然后尝试遵循逻辑。即使有适当的缩进,由于空白行也使我们有机会看到一口大小的块,所以这在精神上会令人筋疲力尽。我必须维护一些不使用大量垂直空白或缩进的代码,因此添加它是我进行自我保护的首要任务之一。
Tin Man 2010年

2
我同意100%。空格用于将代码故意分成逻辑块时很有用。但是,为了没有空格,空格与没有空格一样糟糕。一位前同事喜欢在几乎每行实际代码之后放置一个或多个空行。我花了大量的时间进行“重构”,其中涉及敲击Backspace数千次以删除无用的空白行。
Mike Spross

我添加了一些数据来支持您的立场。请参阅:meta.programmers.stackexchange.com/questions/1109/...
杰夫·阿特伍德

2
这些数据只字未提空行,只有约压痕..
Blorgbeard

21

是的,为了清楚起见。

就像我在这个答案中所做的一样。


13

我可以,但是请确保将

(This line intentionally left blank.)

在线上


1
带注释的白线可能会引起代码的注意
JulioC 2010年

1
多数民众赞成在很多评论中说“此行故意留为空白” ...您不能假设如果某行是空白,那是有意的,否则就不会通过代码审查吗?
替代

43
也许只有我一个人,但我以为OP在开玩笑...
JSBձոգչ2010年

7
您在IBM工作了多长时间了?
纪尧姆

12

是的,但我不会滥用它。

我已经看到了代码,其中方法内的每一行代码都由一个空行分隔,并且在发生逻辑分离的地方使用了两个空行。在我看来,这甚至使其可读性更差。我还看到空白用于疯狂对齐,例如:

//Prot.   Return type                    Name                 Arg1        Arg2
//=====   ============================== ==================== =========== ========

private   int                            AMethodWithALongName(string s,   object o)
{
    ...
}

private   IDictionary<MyLongObject, int> SomethingCrazy      (string s)
{
    ...
}

protected void                           Foo                 (string str, object o)
{
    ...
}

相同的对水平空白的滥用可以应用于垂直空白。像任何工具一样,明智地使用它。


1
看起来像是在入门级大学课程中可以用来驱动某些概念的东西。这实际上是在专业环境中使用的吗?
rjzii 2010年

1
@Rob:它用于大型系统的生产代码中,但没有注释头,并且具有足够大的方法主体,这种对齐使我感到困惑,因为在该文件中看不到其他方法签名。当我折叠方法的主体时,我能够看到空白的“原因”。
Allon Guralnek,2010年

这可能在头文件或接口文件中起作用
Ming-Tang 2010年

因此,编写缩进方案的人将新方法添加到类中,并且该方法的返回类型长于现有返回类型中的任何一种,他将重新制表中所有其他方法的空格缩进类?
Mike Clark

@Mike,在高中时,我们使用了一本Java编程书(不记得书名),明智地建议不要使用这样的水平间距,这仅仅是因为它最终浪费了您必须进行这种重新制表的时间。
马修·弗拉申

5

由于以这种方式编写代码,我受到了很多批评。我不明白为什么有人不会这样做。

可读性非常重要,当您经过很长一段时间后回到一个项目时,我听说过“如果下一个正在阅读的人是知道您所在位置的变态反应者,则总是编写代码”。


您所做的假设是,对代码进行解压缩有助于提高可读性,但我认为这并非总是如此。
杰森·贝克

杰森说了什么。当我回到代码库中时,我希望每个屏幕具有尽可能多的LOC,以便可以快速消化它。如果有人在空白页面上放了半页(或者上帝禁止使用这些可怕的xml风格的注释之一),我很想暂时重新格式化它,只是为了阅读它,然后undo再做几次工作(格式化战争不会提高工作效率,因此我不会直接删除评论和空格,但我的首选是反对它们)。
Inaimathi 2010年

一堵文本墙几乎是不可能阅读的,更不用说人类心理学倾向于抵抗它了。我认为花时间将相似的语句分组在一起,对操纵相同变量的代码行进行分组也很好。我想这都是首选,但是我认为在这项业务中完成的任何事情都绝不能很快完成。
布莱恩·哈灵顿

5

我并不总是写软件,但是当我写软件时,为了清晰起见,我使用空白行。


4
我也经常写硬件,然后打印。便宜得多。
蒂姆·波斯特

5
Equis开玩笑吗?
Paperjam

@Tim实际上,它并不那么有趣:3D打印 ;)(而且…很好,我们在这里并不是所有以英语为母语的人:)。
Takehin 2010年

1
@takeshin我并没有嘲笑任何人,而且我在暗示3D打印。是的,但此评论只是出于开玩笑的意思,我想您可能会误解其意图:)此外,@ Paperjam在一个关于印刷的笑话下评论的事实是..好..无价的:)
Tim Post

我不写软件,但要硬连线。
mlvljr,2010年

5

我全力以赴,使代码尽可能清晰,而空格通常是实现此目标的有用工具。但是,我们不要忘记重构:

  • 在一个类中,我将组合在一起的方法,同时将它们与下一组分隔为空白。

由于您有几个相关成员,因此他们是新课程的候选人。

  • 如果我需要写评论,通常会在评论前放一个空白行

每当代码不清楚以至于需要注释时,我都会问我是否可以重构以使代码足够清晰而无需注释。

  • 在一种方法中,我在过程的每一步都写一个段落

为什么不为每个“段落”采用一种方法?

如果您在类中遇到了很多方法,请参阅上面有关提取新类的说明。


5

是。这样可以更直观地查看文件。除其他事项外,它可以使注释更清晰地显示在哪一行。

Some code here
// Which line does this comment go with?
More code here

// It's pretty clear which line this comment goes with
More code here

Still more code here

4

我谨慎而一致地使用空白行,一致地比谨慎地重要。然而:

  • 如果每一行代码都由空行与下一行隔开,则空行过多。
  • 如果对于放置空白行既没有韵律也没有理由可辨别,那么它们会分散注意力,通常它们太多了。
  • 如果函数太大以至于需要很多空白行,那么它太大了。
  • 如果一个代码块在其之前或之后需要多个空行,则可能会误入歧途。
  • 如果函数之间有两个以上的空行,则可能有太多的空行。

其中大多数并没有引起争议。可能是这样。我注意到,在行尾带有大括号的K&R表示法通常令人沮丧,其后是空白行。我个人不喜欢该行末尾的花括号,而是在花括号使符号(IMNSHO)变成废话之后将其与空白行混合。将大括号单独放在下一行,您的行几乎为空白(IMNSHO的代码更具可读性)。如果必须在行尾使用K&R括号,请不要浪费多余的空白行来节省垂直空间。

// I don't like this
if (something == anotherthing) {
    print ...
    update ...
}

// I much prefer this
if (something == anotherthing)
{
    print ...
    update ...
}

// I loathe this - not least for its inconsistent spacing
if (something == anotherthing) {

    print ...
    update ...
}

// I loathe this too, for its absurd waste of vertical space
if (something == anotherthing) {

    print ...
    update ...

}

3

写出最清晰,最不令人惊讶的内容。

function validEmail($addr) {
    $regex = "/.../";   
    return preg_match($regex, $addr);
}

此功能不需要12行文档注释。

实际上,它不需要任何评论。

或空白行。

他们会损害其本质。


1
顶部的注释描述了接受哪些地址会很好。是否可以使用正则表达式真正验证电子邮件地址?
凯文·克莱恩

3

里面的功能?很少

如果我有一个明显不同的块,则它将重构为一个新函数。如果少数情况不值得。

对我来说,函数内的空白行是最错误的“最佳实践”之一。


2

经常

将其用于经过类似处理的逻辑代码块。添加注释以表明您正在执行不同的步骤后,就可以提取方法了。

良好的空白

{
    int x = computeX();
    x += ADJUSTMENT_FACTOR_X;

    int y = computeY();
    y += ADJUSTMENT_FACTORY_Y;

    setPosition(x, y);
}

错误的空白

{
    //Open a connection
    String serverAddress = lookupAddress();
    Connection connection = openConnection(serverAddress);
    connection.login(user, password);


    //Go get stuff from the server
    item1 = connection.get(1);
    item2 = connection.get(2);

    //Close connection
    connection.close();

    //log data
    log(item1);
    log(item2);

    //Update client
    gui.updateView(item1, item2);        
}    

{
    Connection connection = openConnection();
    updateData(connection);
    closeConnection(connection);
    logUpdate();
    updateGui();
}

{
     updateDataFromServer();
     logUpdate();
     updateGui();
}

4
我假设您的Bad Whitespace示例是应该被视为错误的简化版本。以目前的长度,似乎没有必要将其拆分。
Allon Guralnek,2010年

1
我看不出为什么不好还是不好,为什么你写VS

5
这些评论都不是无论如何需要,为什么在世界将一个提取connection.close()closeConnection(connection)
替代

只要代码块简短且很少,带有注释的代码块比提取方法要好。提取方法不是免费的;它具有代码本地化成本。
克雷格·吉德尼

您只是创建item1item2全局变量,方法通过它们进行通信?ck!
TMN 2012年

2

我不仅使用空格,而且为了清楚起见,还使用大括号。

我常说的花括号可能是功能。

code
{
    code
    code
    code
    code
}
{
    code
    code=code
    code
    code

    code()
    code()
}

2

一次,我会在我的代码中随意添加空白行。如今,我倾向于更加谨慎。我认为这是Steve Yegge在这里谈论的一部分:

希望到目前为止我所画的场景可以帮助您理解为什么有时您看着代码而立即讨厌它。如果您是n00b用户,则将看一看经验丰富的代码,并说这是一个从未学习过现代软件工程基础知识的人所撰写的难以理解且不受纪律的废话。如果您是资深人士,您将查看n00b代码,并说这是实习生在一夜暴饮暴食中可能写的过度修饰的装饰性绒毛。

症结是耐压缩性。当您在职业生涯中编写代码时,尤其是当代码跨越非常不同的语言和问题领域时,您对代码压缩的容忍度会增加。这与从阅读带有大文字的儿童读物到逐渐变得复杂的,带有较小文字和较大单词的小说没有什么不同。

...

对压缩具有高容忍度的程序员实际上受到屏幕讲故事的阻碍。为什么?因为为了理解代码库,您需要能够将尽可能多的代码打包到脑海中。如果它是一个复杂的算法,那么一位资深的程序员希望在屏幕上看到整个内容,这意味着减少空白行和内联注释的数量,尤其是那些只是简单地重申代码在做什么的注释。这恰恰与n00b程序员想要的相反。n00bs希望一次只关注一个语句或表达式,将所有代码移出视图,以便他们集中精力大声喊叫。

我从根本上同意他的看法。压缩代码要好得多,这样一来,您可以在一个屏幕上获得尽可能多的代码,而不是将它们过多地隔开。这并不是说您永远不要使用空行。只是我认为,除非您尝试创建的分组不会极大地提高可读性,否则弊大于利。


2

一位名誉教授给出了两个很好的建议

  1. 空格是免费的
  2. 不要使用钉在纸张前端的钉书钉,否则我会让您失望。

1

我的经验法则是:

  1. 如果我在阅读昨天编写的代码时遇到麻烦,则可能需要提取一个或三个方法。

  2. 如果我的类定义太长而难以阅读,则可能需要提取模块/接口/对象。

  3. 方法定义:添加一行

  4. 模块/类定义:添加两行


1

我喜欢将空白视为与段落相同的方式。您将有助于一个创意的线条组合在一起。

如果您要开始一个新的想法或同一想法的一个新方面,则可以开始一个新的段落-这样。

在命令性代码中,我将执行一项内聚任务的任务归为一组。在声明性代码中,我将描述一个思想的整体说明的代码组合在一起。

您显然不会用英语来做到这一点(有些人对段落很恐惧),因此,稍加练习,将相同的技能应用到代码上就一点也不费劲。


1

我认为空白行是必须的。我用它们来分隔不同的逻辑代码块。使代码可读。可读的代码是好的代码;)

我理想的代码段是将每个逻辑块用空白行分隔,并在每个具有主要逻辑的块的顶部添加注释。

当然,如果人们通过在各处添加多个空行来做到这一点,我会觉得很烦人:(


1

我只在函数/方法中使用空格来分隔声明和代码。

如果您需要用一些行来分隔实现某些逻辑的代码子块,那么它们应该在另一种函数/私有方法中。由您的编译器决定不增加太大的开销。

通常,在peusdo代码中:

def function(arg1, argn, ...)
    INITIALIZERS

    CODE
    BLOCK_START
        INITIALIZERS

        CODE
    BLOCK_END
    CODE
end

如果看到无用的空格,我通常会畏缩。


看上去有点像C-ish,我的C ++编码标准建议不要在不初始化对象的情况下声明它,这避免了这种用法:/
Matthieu M.

@Matthieu M:好的,然后用INITIALIZERS代替DECLARATIONS。但是我永远都不想在中间看到INITIALIZERS。如果需要的话,那是需要较小范围的东西,因此它需要一个私有方法/函数。
haylem 2010年

0

空白非常宝贵。

这很重要……写像E = MC 2这样的复杂代码的书呆子非常擅长展示他们的编程技能。

现在让我们前进六个月,现在是凌晨2:00,并且六个月内未查看的系统已在E = MC 2的行上中断。这几乎是不可能调试的……每个人都吓坏了。

假设代码看起来像这样...

See Dick
See Jane
See Dick and Jan

如果是2:00 AM并且代码已损坏。快速浏览即可了解到第三行应该是

See Dick and Jane

问题解决了。

底线...使用空格。


1
恩...这些例子都没有真正支持您的观点。就我个人而言,我认为E = MC2比E = MC 2更具可读性(最底线是使用空格,对吗?)。哦,除非您还在读高中,否则我敢肯定,比“书呆子”,您可以想出一种更好的方式来指称您不同意的人。
杰森·贝克

@Jason-好点,不好的单词选择。E = MC2更具可读性,这不是我想要理解的重点。就像您在网站YAGNI和SYNDI上谈论的那样。jasonmbaker.com/tag/programming
Michael Riley-AKA Gunny,2010年

0

正如许多其他人所述,空行使代码阅读更容易。但是,有些语言可以强制执行此标准。我可以想到的一个就是Python(不是空行,而是适当的缩进)。


0

我同意,我以相同的方式使用空格。但是,如果我发现自己使用空格将方法分成太多部分,则可能是一个迹象,我可能需要将该代码重构为多个方法。方法中的逻辑部分过多可能表明该方法将更难测试。


0

我用它们将代码分成逻辑单元。我见过很少的代码示例不使用空行,当然,混淆是例外。


0

变态反应的答案是最好的,但我将假设下一个人是一个白痴,并假设他们是您,并且想证明他们是错误的,来代替。

对可读性同样重要的是使用注释。我用注释块打开每个函数或子例程,以明文形式说明其含义,作用,自变量是什么以及预期的结果是什么(包括错误条件列表)。因此,毫无疑问它打算做什么和/或打算做什么。它所能达到的目标可能会有所不同,但这远非如此。

我认为太多的编码人员要么以为是他们自己会对代码进行“修复”,要么根本不在乎。


0

空行很重要。但是,在开括号上浪费整个空白行会减少您在屏幕上看到的代码量。应该:

for (int i; i < 10; ++i)
{  if (i % 3 == 0) continue;

   array[i] += 2;
}

(不要让我开始将花括号'{'与'for'放在同一行上...那是Meshuggah)。


2
是。我想在一个屏幕上查看您的全部功能。不要将花括号放在自己的行上。这就是缩进的目的。
KevBurnsJr,2010年

大括号本身的重点是明确定义代码块。在大括号后面添加一行代码破坏了坚持这种宗教的唯一原因!您也可以将其与“ for”放在同一行。
加里·威洛比

0

是。为了提高可读性。有时,我什至将空行放在我未编写的代码中。当他们通过空行进行逻辑分组时,我发现更容易理解代码-就像您可以“快速读取”代码一样。


0

我们应该像写字母时那样在代码块之间使用空行。

例如,在函数之间或完成循环时在函数内部...

人们必须对代码进行维护才能感谢您;


0

我们使用Microsoft StyleCop推荐的whitespacing。除了可读性和一致性之外,我发现(在较小的类中)正确布置的代码可以在团队中的各个人员碰巧在同一区域工作时更轻松地管理合并。

我不确定这是否只是我的想象,但是差异工具似乎可以更好地识别等价的代码在合并时(整齐地排列)在何处开始和结束。精心布置的代码是合并的一种乐趣。好的,那是个谎言-但至少痛苦可以保持在可控制的水平。


0

切勿在整个文件中都没有空白行。这并不是说代码没有中断:

 code;
 //
 morecode;

空行用于打开要处理的代码部分,编辑器中有几个热键可带您进入上一个/下一个空行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.