微信号:Engineer_First

介绍:坚持分享一线攻城狮的实践、学习心得 路漫漫兮修远矣,一路同行

聊聊代码规范

2016-04-22 12:26 halty

不论在哪一家公司,不论是哪一种语言,工程师们总会或显式或隐式地逐渐形成一种编码约定,这其实就是编码规范。今天,我们在这里简单的聊聊代码规范。由于平时工作中涉及的编程语言主要以Java为主,所以下面讨论的主要是Java代码规范,不过有些思想对其他的语言规范也同样有所借鉴。

1. 为什么需要代码规范

在谈论具体的代码规范内容之前,我们先思考一个问题:为什么需要代码规范?或者说代码规范主要是用以解决什么问题? 在我的理解中,一份代码规范主要解决以下几个问题:

(1) 交流沟通效率问题

从个人的代码规范而言,一致的代码风格,对于你隔一段时间回过头来看自己以前写的代码,能够很大程度上减少自己重新梳理的成本。

扩大一点范围,从个人所在的团队而言,一份代码规范,能够减少团队同事在互相backup时,接手遗留项目时,新同事熟悉团队Code Base时的理解成本。一旦能够快速有效理解代码的话,就实质上已经降低了沟通成本。

再扩大一点范围,从个人所在的整个公司而言,代码规范能够有助于跨团队合作时熟悉彼此接口交互,能够极大减少移交/接手其他团队Code Base时的理解和沟通成本。而这个理解和沟通成本往往是影响项目迭代的首要因素。

再再扩大范围,从某个编程语言的范畴而言,代码规范能够很好的降低某个编程语言开发者之间的交流沟通成本。而开发者的技术水平的提高,往往都离不开社区、个人彼此之间的交流沟通。特别是你参与到一个开源项目或者你发布一个开源项目时,制定一份合理的代码规范,往往是项目发展壮大过程中必不可少的一个重要步骤。

(2) 犯错误概率问题

首先,交流沟通本身就存在一个理解偏差的问题,而代码规范在一定程度上就明确了某些场景下的一些模糊问题的定义,从而能够减少由于沟通理解偏差导致的犯错概率。其次,一份好的代码规范都是在具体某个编程语言最佳实践的基础之上制定的,并且随着时间不断迭代改进。这些最佳实践本身大都是前人的失败错误经验总结,当然能够很大程度上降低编码犯错的概率。

2. 一份代码规范主要包含那几个部分内容

计算机编程能够解决的问题,肯定在现实生活中已经有既定的解决方案。计算机编程实际上可以看作是一个通过编程来对现实生活问题解决方案进行再创造的过程。在这个过程中,不同的编程劳动必定存在一些共性和差异的地方,这反映到不同的代码规范中,也必定会有一些共性的规范和差异。

一份好的代码规范包含但不仅限于下面几个部分内容:

(1) 代码结构规范

在Java编程语言中,Maven的代码组织结构,已经成为既定的一种代码结构规范。

src
|-- main
    |-- java
    |-- resources
    |-- webapp
    |-- scripts
    |-- assembly
|-- test 
    |-- java
    |-- resources
LICENSE.txt
README.txt

(2) 格式化规范

常见的格式化规范主要包含以下几种:

  • 规定'()','[]','{}'的格式化;

  • 规定代码块的缩进;

  • 列长度限制;

  • 空格及转义字符的要求;

  • 类的声明、构造、初始化格式;

  • 变量、数组等声明、初始化格式;

  • 语句的格式;

  • 类、变量等修饰符的声明格式;

  • 注释、字面量的格式;

针对具体的语言,可能还会有一些特有的格式化规范,例如Java语言代码规范往往还会包含下面几种:

  • import的格式化;

  • 对象属性、类属性、对象初始化块、类初始化块等组织顺序要求;

  • package的格式化;

(3) 命名规范

以Java语言编程规范为例,主要包含以下几种命名规范:

  • 包命名;

  • 类命名;

  • 方法命名;

  • 常量命名;

  • 对象属性命名;

  • 参数命名;

  • 局部变量命名;

  • 类型变量命名;

  • 配置文件命名;

一个Java语言中普适的命名原则:Camel case(驼峰式)。上述不同的标识命名规则大都以此基础上,再做细微调整。例如:对象属性命名,通常以首字母小写开头,后续每个单词的首字母大写,如xmlHttpRequest。更详细的Java命名规范可以参考《Clean Code》[中文名:代码整洁之道]

(4) 最佳实践

同样以Java语言为例,一些被普遍接受的最佳实践:

  • 总是标注@Override;

  • 总是catch Exception;

  • 总是通过类来引用其静态属性;

  • 不使用Finalizer;

  • 在Override类的equals方法的同时,要Override hashCode方法

  • 不使用对象的初始化块;

更多的Java最佳实践可以参考《Effective Java》。

在这个基础之上,公司或者团队往往会总结并沉淀下来一些内部的最佳实践。例如:

  • 如何实现安全的单例初始化;

  • 如何合理地使用线程池;

  • 如何合理地使用List、Map、Set等Java Collection;

  • 如何正确地使用HttpClient、Netty等开源类库;

而上面这每一个最佳实践扩展开来,往往都需要一到多篇文章来讲解。后续有机会针对这块单独再聊聊,在此不表。

(5) 文档规范

公司、开源项目都会定义项目的文档规范。以Java语言为例,一般指Javadoc的规范,然后通过工具自动生成html等不同格式文档。一般的Javadoc规范主要包含以下几点:

  • 基本格式(包含一些格式化的标签);

多行的Javadoc:

/**
 * <p>Multiple lines of Javadoc text are written here</p>
 */

单行的Javadoc:

/** An especially short bit of Javadoc */
  • 代码中何处该使用Javadoc;

一般在每个public的类及其pulic或者protected的(属性、方法)上需要使用Javadoc进行说明。

  • Exception的标注

一个特别需要说明的规则:就是每个public或protected方法最好在其Javadoc中标注其可能会throw出的Exception(不论是RuntimeException还是非RuntimeException),并解释在何种条件中会throw出何种异常。

3. 如何制定和践行代码规范

在梳理了代码规范的目标之后,参考一些开源项目或者业界知名公司的代码规范,再结合自己公司的业务特点,往往比较容易制定出一份代码规范。但问题是有了制定好的代码规范之后,工程师们往往无法在实际的实践过程中,切实践行代码规范。

其实无法践行代码规范的一个最主要原因就是:

工程师,或者说公司对代码规范的重视程度不够

在我工作过公司里面,也有曾经推行过代码规范。在践行规范的初期,必定有一段磨合期。如果一个工程师自己的编码规范跟公司制定的代码规范的匹配度很高,磨合就会很快,但不可避免的有部分工程师的match程度有待提高,这必然会影响工程师的开发进度。在项目进度的压力下,如果工程师或者公司对代码规范的重视程度不够,代码规范往往是第一个被废弃的,KPI is first。

如果有足够的重视,是否意味着就一定能够在工程师中有效地践行代码规范呢?答案是No。但拥有足够的重视,至少是一个不可或缺的开始。

  • 工程师重视代码规范

在我的理解中,对于工程师而言,主要有2种能力:编程能力(数据结构、算法、领域建模等)和工程能力(编程语言最佳实践、编程工具使用、库或者框架的合理选型和使用等)。一份好的代码规范不一定能够有效提高你的编程能力,但是肯定可以提高你的工程能力。而在很多的工作岗位上,其实对工程师的编程能力要求并没有那么高,更多的是工程能力。在提高工程师自己工程能力的同时,切实践行代码规范能够很大程度减少自己犯错的概率,提高系统的稳定性、可用性,交给公司一份好的工作成绩单,双赢。至于如何提高自己的编程能力和工程能力,这又是一个很好的话题,有机会下次可以聊聊。

  • 公司重视代码规范

对于公司而言,最好的重视手段就是将其纳入流程。通过流程化来保证代码规范的切实践行。例如,基于一些成熟可用的插件,在CI阶段check工程师commit的代码,保证commit成功的代码符合规范;同时在Code Review阶段,强制要求Review提交代码是否符合规范。

人都是有惰性的,肯定有一段践行代码规范的初始阵痛期,但是一旦迈过了这个阶段后,在这方面的(产出/投入比)会越来越大。尝到甜头,后续自然反应不会那么大。

最后,这个代码规范,不应该是一个静态的文档,而应该是一个动态持续构建的文档。在实际实践过程中,会总结、提炼一些新的规则、最佳实践等,进而不断完善规范,而完善后的规范又能更好的指导实践,构成一个闭环反馈。

4. 可参考的文档

(1) 关于具体规范

Java规范可参考《代码整洁之道》https://book.douban.com/subject/5442024/

通用规范可参考《代码大全》https://book.douban.com/subject/2208626/

(2) 一份实际可参考的代码规范

Google Java Style https://google.github.io/styleguide/javaguide.html

(3) 关于最佳实践

《Effective java》https://book.douban.com/subject/3360807/


硬广:扫描下面二维码,关注公众号[一线工程师],不定时干货分享!^_^


 
一线工程师 更多文章 Folly源码分析系列(一) — ThreadLocalPtr
猜您喜欢 头条 ┃ “大数据”概念消亡预测为时过早 关于大数据的十个有力事实 逆向分析网络协议 iOS 篇 CDN如何为移动端加速? 流利说@WWDC 2016 PHP多种序列化对比