编码标准:纪律和人因工程的双剑合璧

0. 引子

说 起编码风格,每个人都有一些自己的见解。简单牵狗一下,发现类似的资料层出不穷。除了不少开源项目使用的编码规范以外,还有不少据说是从业界一流公司流传 出来的,甚至更有专门的论述。wikipedia上也可以发现专门的对C++常见编码风格的分类和一般讨论。这里,我们试图分析不同编码标准背后蕴含的真 实意图。这样,我们就可以合适地评价不同的编码风格,并且可以在实际使用的时候做出合适的选择。

 

代码是写给人而不是机器的,这是一个常识。特别是当相当规模的组织在协同构建代码的时候,深入理解这一点更具重要意义。有时候,人们常常把编码风格 仅仅看做是一种团队纪律。这是正确的,但是却远远不够。本质上,不同编码风格的形成和我们对编码风格的特别要求,都有源于使其更适合人——任何的代码构建 维护过程中都起决定性作用的角色——来使用的需求。专门研究这类特性的叫做人因工程,该学科探寻的如果组织与人交互的外界的事物,是人更具生产力。

 

其实不用求助于什么人因工程,“好用”两个字概括出了我们追求的终极目标。对于代码,“好用”表现为:

1. 结构整齐,外观协调一致

2. 逻辑清晰,合理组织

3. 易于理解,不违反直觉

4. 主次分明,层次有序

 

使用程序员的话,那就是:

1. 代码行不能太长。22寸的显示器,全屏还需要滚动条才能完整浏览一行的显然不行

2. 代码幅度不能太大。一个函数有几百行很显然不利于阅读

3. 业务逻辑集中且脉络清晰。维护工程师最讨厌的情况就是一个完整业务逻辑链的各个环节分布在各个不同的地方,或者其中几步深深隐藏在一个毫不起眼的调用中;

4. 一致的风格。一些工程师有一个习惯,任何外部的代码都必须使用他自己的工具重新格式化以后才开始阅读。

 

完 整讨论所有影响到编码风格的因素需要相当的篇幅。我们这里仅仅取其中最简单,但是也最容易被忽视的一些地方。事实上,正式这些最基本的东西,构成的大部分 编码风格的基石。我们需要的不是学习应用这些风格,而是真正理解其背后的东西。本文的期望是,初学者在阅读本文之后可以写出规范的代码。这是工业强度代码 的最基本的要求。

 

1. 行长

早期,基于文本的计算机显示器一般都是25*80大小,这是为什么好多编码标准仍然要求每行代码不超过80个字符的原因。现在,越来越多的

人认识到大屏幕显示器对程序员工作效率的重要性,19寸以上的显示器在日常工作中非常普遍。仍然拘泥于每行80个字符似乎没有必要。但是,因为如下原因,80长度限制仍然有必要:

1. 有的人喜欢打印代码出来阅读,每行80字对普通的A4纸张正好合适

2. 由于操作系统的缘故,大屏幕显示器不能发挥作用,仍然只支持基本的25*80。不过这似乎不是很明显的限制,因为好多的程序员喜欢使用基于图形界面的工具编写代码,然后到目标机器编译执行。

如果这对你都不适用,你可以简单地忽略80字符限制。但是,最好不要超过120字符。一个判断标准是,不需要滚动水平滚动条,你就可以看到全部的一行代码。另一方面,如果一行必须使用多余120个字符才能表达,我建议你重新考虑这行的构造和作用。

 

2. 缩进

程序员早就认识到缩进给阅读代码带来的好处,但是直到支持自动缩进的编码工具发明之前,大部分的程序员都不能有效地协调一致使用缩进,程序员根本没 有时间一个一个敲入那些用来对齐的空格!在现在,当一个编程工具不支持基本的甚至智能的缩进的话,就根本不能够在市场上获取任何的优势。所有这些工具都支 持配置缩进的宽度,使用空格或者制表符(/t)填充。

默认的制表符的宽度是8个字符宽度,这对于几乎所有人来说都是太宽了!太宽的缩进导致一行所能表达的代码极其有限,所有现在的编辑器默认都是4字符 宽度。但是仍然有不少的编码规范要求使用2字符宽度的缩进,这样以可读性稍微的下降来换取更长的实际代码行。由于阅读代码是主要的工作,所以除非有特殊的 限制,建议使用4字符宽度的/t缩进。还有一些妥协的策略使用3,一个奇数,似乎不是程序员的风格,但是确实有这样的项目。

 

由于/t宽度的不确定,一些编码标准强制要求使用空格而不是/t,这样可以保证在任何编辑器中可以看到风格一致的代码。这样做有几个小问题:

1. 对于稍微大一些的源文件,使用空格代码/t常常会使得源文件的大小增加几十K

2. 当智能的缩进不起作用时,手工插入或者删除用于缩进的空格使人厌烦

所以,建议使用/t,并且确保组织内部就/t宽度达成一致,并且使用的代码编辑器或者查看器设置一致,如果你同时使用多个编辑器的话。

 

3. 大括号的位置

在网络上浏览,很容易注意到两种不同风格的代码写法。第一种是大括号单独占一行(这是推荐的)

 

另一种是大括号和前面的语句占同一行

 

它们的背后的区别在那里?

当大括号单独占据一行时,代码的纵向长度就要大一些,这样可以确保在一个屏幕内看到更多的代码。由此可见,其背后的原因也是尽量避免使用垂直滚动 条。除非之外,二者所表达的含义完全一样。对于此,没有特别的建议,根据个人爱好选择即可。但是,需要提醒的是,使用第二种的理由在现在的环境下并不充分 了:

1. 屏幕变得更大

2. 如果在一个更大的屏幕内,一个函数的实现都需要滚滚垂直滚动条才能浏览完毕的话,可以认定该函数做了太多的事情,考虑重构之

 

还有一种看似此类风格的变体,其实完全体现了另外的思想。它的格局如下:

 

此种缩进风格中,大括号和其内部的语句对齐。它强调的是语句的逻辑联系。一个块的定义是从{开始,到}结束,所以这样是块的概念更加完整。这是有道理的。然而,这并不很符合直觉:

1. 尽管{和}事块的开始和结束,但是它们本身并没有实际的作用

2. 对于专门依赖块结构的语句(例如局部锁),使用后的风格让人感觉很奇怪,例如

结论是不推荐这样的写法,而且事实上,使用该风格的也很少。

 

对于大括号体内语句很少的情况,是代码纵向变短的优先级就大于使用独立缩进的优先级了,下面是两个例子

这种情况下,当一行较长时,使用另一行。但是是整个函数体都缩进。这样既保证了可读性,有节省了纵向空间。

 

4. 小括号和方括号的位置

对于小括号的使用,虽然一般区别不大,但是仔细观察,还是有一点差别。常见的有两种风格。第一种是“外向型”:

特点很明显,在括号内侧都包含额外的空格。另一种是“内敛型”,与外向型相反,它要求括号的内侧都不包含空格。

这里推荐使用内敛型,因为括号中的内容本身应该在逻辑上联系更加紧密,紧密的括号可以强调这一点。这也符合我们一贯要求的把相关的东西放在一起的基本原理。大部分的代码都是符合内敛型。但是具体用什么,这里完全是个人喜好或者团队纪律在起作用。

 

5. 空格的使用

有效地使用空格可以是代码变得结构清晰,易于阅读。C/C++代码都是自由格式的,这就必须强调一下空格(包括空行)的使用。一些多格式严格要求的语言,如Python,基本上不存在这样的问题。

我们的指南是,尽量使用空格,但是不滥用空格。一个常见的用法是使用尽可能多的空格:

这个例子可能有点过分,但是它非常容易让我们意识到滥用空格的坏处:

1. 更多而击键操作

2. 松散的代码结构,不能突出主题

 

不用空格和尽量少用空格的例子就不再举出。我们很容易就可以认识到其不足。这里直接给出本文要提倡的观点是: 使用还是不使用空格空行,完全依赖于是否能准确表达代码背后的意图。下面列出一些基本的原则:

1. 关键字的操作符都要使用空格分开,而一般的方括号和小括号不使用空格。参见上面关于方括号和小括号位置的讨论;

2. 使用空行隔离逻辑相关独立的代码段。常见的情况是,一个代码段有一段相应的注释,而注释之前一般有一空行

 

下面是一段简单的示例代码

 

6. 命名

合 适的命名非常重要。我们建议使用清晰的名字来表达对象的含义,但是不要使用太长的名字。总的说来,对象的名字的长度和其生命周期成正比。所以,具有全局含 义的变量要使用较长的,据描述意义的名字(习惯了这样,就会促使你尽量减少全局对象的数目,合格的程序员的重要特征之一就是懒得);而局部的对象则可以使 用较短的名字。对于循环变量,传统的i,j,k依然很受欢迎。

 

对于强类型的语言,人们喜欢在命名的时候给对象名字加 上一个合适前缀或者后缀来表达其类型或者作用。特别是当匈牙利命名法在windows编程领域大行其道的时候,带类型标识的名字很是常见,尽管有时候只不 过是匈牙利命名法的变体,误用,甚至滥用。C++社区不推荐使用匈牙利命名,基本理由之一是对于泛型来说,对象的类型是未知的,难以适用。这个理由站得住 脚,但是不够充分。

 

一种语言室强类型的,使用为该语言会使用严格的类型检查来编码程序员无心的错误以及为更有效优化 提供支持。由此可见,强类型对编译器至关重要,而对程序员的意义并不大。编译器并不会因为你使用了错误的类型前缀而抱怨。编译器根本不需要任何的名字,只 要对象之间可以使用合适手段互相区分即可。对于程序员来说,使用有意义名字的好处是可以快速理解对象除了名字之外的其他(部分)属性,如类型。有时候这对 于理解代码很有意义。不行的是,如果必须知道一个对象的类型才能有效理解代码的话,我们可以安全地认为这样的代码存在易读性上的问题。良好的代码有一个明 显的特征就是自文档,它根本不应该依赖于什么类型。类型,只是实现的选择之一。这里,我们可以看到,程序员的需求是可以快速理解对象本身或者在上下文中的 含义。使用简单的类型前缀根据就无助于这样问题的解决。

 

结论是,尽量使用其他的手段来明确你的意图,而不是通过类型 暗示。实践中,使用普通的名词,动名词作为对象名字比使用类型前缀更直观。当然如果你的项目中大量使用某种类型匈牙利的命名方法,我建议你还是保持一致的 风格为好,因为你的同事已经习惯了这样的命名,并且形成了特别的直觉。贸然打破这样的直觉只会使人感到沮丧,并且影响效率。

 

对于类成员变量,有一种习惯是在名字前使用前缀下划线。这很流行,但是由于C++标准吧所有的以一个和两个前缀下划线的名字作为保留

, 现在C++社区推荐使用后缀的下划线。我个人比太喜欢这样,因为在某些类浏览器中寻找一个成员变量变得不再直接。有一些实现喜欢把所有的保护或者私用的成 员,无论是变量还是函数,都使用前缀或者后缀下划线;而公共的成员都不使用下划线。不推荐这种做法,因为使用的项目非常少。

 

至于为什么一定要使用前缀或者后缀下划线,基本原因是它使得如下的代码成为可能:

使用非常少的名字就可以表达丰富的含义。没有下划线,就需要不同的名字,这常常不容易。

 

最后一个关于名字的选择是使用ObjectName还是object_name风格。二种风格都很好,只要保持一致就行。Windows API喜欢第二种,而Unix喜欢第一种。C++标准也喜欢第二种。无论那种,项目中保持一致即可。

 

7. 总结

这就是涉及到编码风格的最常用的东西了。很简单,不是吗?作为一个构建工业强度代码的工程师,他要做的不是记住这些建议,而是明白怎么使用有效的工具和手段使代码更具可读性,简单,符合直觉以及高效地实现 。 阅读代码是非常困难的智力劳动。我们根本没时间去矫正由于不合适的代码风格导致的理解偏差。为了消除可能的偏差,那就为了代码的可读性而努力。这里给出一般的建议和指南,它不是要禁锢你的创造性,而是要保证你把时间放在正确的问题上。

 

良好的编码风格是一个合格软件工程师的基本职业习惯。如果你的练习代码都能达到这样的要求,那就已经在迈向职业工程师大门的道路上了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值