C++代码规范与cpplint自动检查

    使代码易于管理的方法之一是加强代码一致性,让任何程序员都可以快速读懂你的代码这点非常重要。保持统一编程风格并遵守约定意味着可以很容易根据“模式匹配”规则来推断各种标识符的含义。创建通用、必需的习惯用语和模式可以使代码更容易理解。虽然在一些情况下可能有充分的理由改变某些编程风格, 但我们还是应该遵循一致性原则,避免代码审查或者任务交接出现不必要的麻烦。

对于编程风格的统一,不仅仅是中小公司面临的棘手问题,对于google这样的大公司,同样存在这样的问题,google的开源项目大多都是用C++开发,正如每个C++程序员都知道的, C++有很多强大的特性,但这种强大不可避免的导致它走向复杂,使代码更容易产生bug,难以阅读和维护。

Google经常会发布一些开源项目,意味着会接受来自其他代码贡献者的代码。但是如果代码贡献者的编程风格与 Google 的不一致,会给代码阅读者和其他代码提交这造成不小的困扰。Google 因此发布了一份自己的编程风格,使所有提交代码的人都能获知 Google 的编程风格。这份规范不仅仅包括了C++风格指南,也包含了C、python、shell和Java。创新工场董事长兼CEO李开复曾经对Google C++编码规范给予了极高的评价:“我认为这是地球上最好的一份C++编程规范,没有之一,建议广大国内外IT研究使用”。

针对C++部分,其主要通过12个章节来约定格式规范,如图1所示,里面针对C++的头文件、类、函数的书写格式做了详细的说明,下面我挑选几个规范做一个介绍。


图1. C++风格指南目录


之所以不建议使用前置声明而使用“#include”,是因为前置声明隐藏了依赖关系,当头文件改动时,用户代码会跳过编译过程。极端情况下,用前置声明代替“#include”甚至都会暗暗地改变代码的含义,如图2所示:

图2. 前置声明示例

如果 #include 被 B 和 D 的前置声明替代,test()函数中,本意是希望形参x可以隐形转化为B然后调用f(B*),但是由于有f(void*)同名函数,导致test会调用 f(void*),偏离本意。



我们使用空格缩进,不要在代码中使用制符表,你应该设置编辑器将制符表转为空格,因为不同的代码IDE中,TAB代表的空格长度不一致,如果更换编译器后,就会导致对齐混乱。这一点在嵌入式开发过程中深有体会,我们写程序一般用vs studio或vs code,编译的时候使用IAR,经常会遇到在vs IDE里面缩进都没有问题,但是在IAR中,如图2所示,缩进会出现混乱的情景,就是因为IAR中TAB代表的是4个空格长度,而vs中普遍为2个空格长度。



图2. Vs code与IAR缩进对比

针对书写格式,c++编程指南也做了一些规范,比如在每个文件前,必须要有版权说明;在代码注释的时候,“//”与注释代码间保留一个空格符;书写函数时,大括号“{”不能另起一行,而是与函数名字间隔一个空格并且保持在同一行;代码块最后的空行要删掉……,有人总结了如下的一张图来说明该指南的规范要求,基本涵盖了所有的格式要求,如图3所示。


图3. C++格式指南说明

可见这份规范对C++的代码格式规定很详细,我只是简单列举了三条作为引入,具体感兴趣的同学可以在\\rd\软件部\Shared\工具软件\cpplint路径下查看具体规范。

[if !supportLists]2. [endif]Cpplint工具引入

有了上面约定好的一系列编码规范,就可以使我们团队每个成员的代码格式保持一致吗?答案当然是否定的,当然还需要再日常编程过程中去逐渐规范并慢慢培养成习惯,但是如果没有有效的控制行为,依靠人力去检查和维护这些格式,无疑是一个非常繁琐和复杂的工作,为此google开发了自己的C++代码规范检查工具—cpplint。cpplint是一个Python脚本,作为一款开源免费的代码静态检测工具,Google也使用它作为自己的C++代码检测工具,也就是说,只要你想代码遵从Google C++代码规范,那么Cpplint将会提供很好的代码静态检测支持。Cpplint的github仓库可以通过cpplint.git克隆到本地。

cpplint由于是python脚本,所以使用起来很简单,直接在命令行通过“cpplint.py {*.cpp}”即可,针对发现的每一个问题,都会给出一个位于区间[1, 5]之间的置信度评分, 分数越高就代表问题越肯定。你可以通过verbose选项控制输出哪些级别,如果代码中有些部分不希望被检查,或者你认为cpplint产生了误报,只需要在行尾添加注释 ‘// NOLINT’, cpplint就会跳过这些行. 如果你想过滤掉特定的警告, 就需要设置filter选项了(-表示不输出, +表示输出), 比如写一个测试文件:


图4. Cpplint 测试程序

打开命令提示符,如图5所示,会发现一共同拥有9个错误,我们需要按照提示信息,将格式修改正确后就可以了。

图5. Cpplint检查到的格式错误问题

虽然可以通过脚本文件对我们的代码进行检查,但是在实际项目中,我们不可能开发完代码之后将代码单独使用cpplint检查一遍,这样不仅繁琐,而且会耗费大量时间去处理。我这里提供三种方案:

在jenkins中配置静态检查工具,每次有gitlab merge request 时,自动触发代码静态检查工具,然后进行代码审查,这种方法适用于项目中,所有提交merge request的开发者。每个人提交到gitlab中的代码必须经过cpplint检查才能符合顺利合并的Dev分支。这种方式需要有gitlab权限的开发人员在服务器部署。

使用vs code或vs studio集成cpplint插件,每当保存完代码文件后,cpplint则会自动运行插件,以vs code 为例,每当文档发生改变自动保存后,就会用波浪线提示不符合格式规范的代码,同时在终端显示提示信息。只需要在安装cpp-check-lint插件即可。这种方式适合程序员提前预知不符合格式规范的代码,确保在提交前进行自检。


图6.vs code中格式警告信息

在每个开发者的本地,通过git pre-commit 钩子来进行适配。利用钩子检查commit的文件,如果提交的代码不符合cpplint的要求,则不被允许提交,相比于在jenkins中配置静态检查工具,每个人可在本地灵活配置cpplint的配置文件,用来设置不同的过滤等级和测试项,这种方式比较适合每个人在本地测试自己的代码风格,并做一些测试,下面我们主要介绍这种方式。

在每个git托管的项目下,都有一个.git的隐藏目录,里面的hooks文件夹默认配置了很多钩子,只不过默认情况下这些钩子函数是不可用的,如果要启用,需要将.sample取消,然后将以下内容拷贝到pre-commit中,并且在第5行配置正确的cpplint路径。



通过以上钩子,可以在每次提交代码时,对所提交的代码文件进行格式检查,如果没有检测通过,则不能被提交到本地仓库,并且也会说明不符合规范的提示信息,如图7所示


图7.git hooks的提交警告


总结

以上介绍了Google 公司的c++编码规范,他系统的规定了我们书写C++的日常规范,同时配合cpplint这样强大的自动检查工具,为他在日常代码编写规范中提供了切实的落地可能。同时介绍了三种在实际项目中,该工具的配置方法,实际在项目中,三种方法并不是冲突的,可以同时配合使用,提高团队成员开发效率。

当然这个工具也有一定的局限性,由于该规范是以文件为单位进行代码检查,并且目前笔者所在T04项目处于尾期,软件功能已完成90%以上,每次修复一个局部bug,都会检查其他代码的规范,如果严格限制格式,就需要将该文件所有代码重新修改,这样给cpplint的推广也带来了巨大的挑战,但是这对公司后期以C++为语言为主的新项目规范还是有一定帮助的。

一个好的规范是需要大家一起去遵守和维护的,规范逐渐地变成了一种习惯才能提高团队的开发效率,享受规范带来的便捷,就像十字路口的红绿灯,虽然从个体出发,会降低通行效率,但是从十字路口的利用率而言,是提高了每个个体的通行效率和路口的利用效率的。

参考文献

[1] https://github.com/cpplint/cpplint.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容