前言
《哪种编码风格是你的“菜”》(英文原文:《Reprogramming My Brace Style Mind》) 中从历史的角度讲述了编码风格的演进。
文中讲述了 3 个年代的编码风格:1980/1990年代的紧凑风格、2000年的宽松风格以及 2010年的典型风格。
各年代风格
1980/1990年代的紧凑风格
紧凑风格的规则有:使用 Tab 缩进、代码限制在 80 列、大括号放在同一行、代码行间不加空行……
这些规则的制定,通常是为了有效规避当时的一些编程环境的“劣势”,其中比较突出的是,从现在的角度看来,小得可怜的硬盘和内存,以及狭窄的屏幕。
因此,使用 Tab 缩进将使源代码文件更小,80 列、大括号同行、不加空行等将使一屏上显示更多的代码。
C代码:
1 | int main(int argc, char *argv[]) { |
2000年的宽松风格
宽松风格基本使用微软的 C/C# 约定,使用 4 个空格缩进、不限制代码行长度、大括号单独一行。
规则变得“宽松”是因为编程环境的改善,存储和显示不再是稀缺资源,因而不用再过度节省。
C代码:
1 | int main(int argc, char *argv[]) |
2010年的典型风格
典型风格称为“Kernighan & Ritchie 风格”,是 C 衍生语言设计者所遵循的风格,其规则为:
当秉承 K&R 时,每一个函数左括号都应在下一行中,并与开头行有相同的缩进。括号中的语句应该缩进,右括号应该与函数开头有相同的缩进,并单独一行。 对于代码块内的控制语句,左括号应与控制语句在同一行中,右括号单独一行(除非有
else
或while
关键字)。
C代码:
1 | int main(int argc, char *argv[]) |
优缺点
各年代风格在它产生的时候,无疑是利大于弊的,否则就不会有这么多程序员遵守,但是,从今天的眼光看,它们其中一些就有点“过时”了, 至少,将不再像当时那般重要了。
下面,我们以今天的眼光来审视一下这些规则当下的价值如何。
Tab/空格缩进?
使用 Tab 还是使用空格缩进代码呢?这是一个永恒的争议话题。 事实上,无论是使用 Tab 还是空格缩进都没有太大的问题,唯一的差异可能是,使用空格缩进的代码在不同编辑器的显示上通常是一致的。 但是,使用 Tab 缩进的代码在不同编辑器里显示可能是不一致的,这取决于编辑器把一个 Tab 替换为多少个字符宽度的缩进。不过, 目前主流的编辑器通常支持用户自定义 Tab 的缩进宽度,这也就不是什么问题了,除非你总是在不同的编程环境中工作,并且总是替换编辑器。
80 列
80 列的宽度限制目前仍然是有益,它迫使程序员写更少而精简的函数名或代码,这本身是一件好事;但同时,如果程序员的能力不够或不在意, 使用了短而不当的名称,那么将使代码难以阅读和维护。但这不应归罪于规则。
80 列还限制了代码不应有过多的缩进层次。过多缩进层次的代码往往说明其中包含了过多不同层次的业务逻辑,应该将不同业务层级的代码抽取为更小的函数。 小的函数更易于阅读和维护,并使代码逻辑更有层次感更清晰。
值得思考的问题是,“80 列”这一限制是在 80、90年代提出的,当时提出的依据多半是显示器的大小,在目前大显示器已经普及的情况下, 坚持“80 列”的限制是否有过于保守的嫌疑?因此,将限制放宽到“120 列”也是普遍接受的。
总之,不论是“80 列”还是“120 列”,有限制总是好的,限制的目的是使每行代码宽度适当,以避免出现水平滚动条。 水平滚动条的出现,将使得阅读代码需要不停左右拖动,影响效率。
也许有人主观认为阅读代码的时间很少,以至于突破宽度的限制对效率的影响也是有限的。这种主观感受是错误的,统计表明,阅读代码的时间比我们想像的多, 甚至比我们实际编码的时间多得多。
左大括号
紧凑风格时代左大括号在同一行,是为了一屏能显示更多代码。
大屏时代,这已不那么必要了。目前的编程风格都倾向于把左大括号放在单独一行中,这使得代码块更加明显,开始和结束点通常很直观。
如果我们坚持小函数的原则,那么在代码块内也将左大括号放在单独一行中,代码块也会很直观而优美,且一屏就可以显示了。 K & R 风格也许并没必要使得函数内部如此的紧凑。
空行
紧凑风格时代不使用空行分隔代码块,是为了一屏能显示更多代码。
但是,使用空行可以使代码更易于阅读。类似功能或者同一子逻辑的代码我们总是倾向于放在一起,组成一个代码块,并与其它代码块区分开的, 而使用空行是最简单而直观的方法。
附录
紧凑风格后遗症
紧凑风格的代码行之间往往不会添加空白行,这使得很难找到代码块的开始和结束标记。因此,产生了一种“怪异”的注释,它用以标记某个代码块的结束。 (可参考第一段代码示例)
但是,可以想像,这种注释的作用没有程序员希望的那样强大。比如,当代码块过长,超过一屏时,注释的效果就会大打折扣了;又比如, 当代码层级过多,有很多类似注释时,很难分清哪个注释是哪个块的结束标记。
事实上,如果函数编写得适当的小,结构将足够清晰,以至于不用使用这种注释的方式标记代码块的结束。
总之,这是一种“过时”的注释方式,是应该摒弃的。