南山行者
作者南山行者·2019-11-27 16:47
系统工程师·某银行

静态代码检测最佳实践

字数 4697阅读 1810评论 0赞 3

摘要:
随着公司规模、业务的发展,项目越来越多,系统复杂性也越来越高,项目管理者意识到代码规范的重要性,国内外大公司,如谷歌、百度、腾讯、阿里、华为等公司都先后制定了代码规范。代码规范作为提高代码质量的方式之一,是一种成本低廉的技术手段,可以做到针对代码进行第一层质量的保证。作为证券经营机构的质量保障人员,我们迫切希望推进代码规范的落地执行,但实际应用中大部分企业都流于形式,没有有效落地,更别提能发挥作用了。
代码规范若单纯依靠人力进行代码审查ROI太低,无法准确反馈,无法实时度量,无法整体分析,无法从组织级衡量进展和成效,这些都是拦在代码规范实施面前的难点。
代码规范的落地须依赖一种可度量、可反馈、可持续改进的服务能力,通过服务化模式运作,降低开发、测试人员的人力投入,以简单的方式完成代码规范的检测、反馈、度量、优化。
本文详细介绍了一种代码规范的运营方案,通过组织搭建、角色定义、过程定义、服务能力构建、虚拟运营团队持续推进的方式来降低成本实现代码规范的迭代运营。
关键字:
代码规范;SonarQube;规则共享平台;
一、 引言

谷歌发布的代码规范中指出,80% 的缺失是由 20% 的代码所引起的。规范的代码可以消除过于强烈的个人风格,有助于代码在项目间高效的流转;提升代码的正确性,降低低级问题产生的可能性;同时也降低了项目的维护成本。良好的编码习惯,可以促进团队的合作,可以减少莫名的bug,可以降低代码维护的成本,可以降低代码审查的难度,可以提升代码的健壮性,助力整个团队代码品质的提升。
但相当多团队的代码规范只是一份文档,原因在哪里呢?通过一些研发人员的调研,得到图1的数据。


1、不想改占比69.77%,主要原因为:
● 人工review代码太浪费时间,项目太赶,没时间。
● 我也知道这么写不好,可既有代码就是这么写的,只改一处也没用。
● 有些规范也很差,还不如我写的规范。
● 不能全盘进行代码规范的落地,都是暂时性工作,没啥效果。
2、不愿改占比18.60%,主要原因为:
● 代码规范就是浪费时间,没用。
3、不会改占比11.63%,主要原因为:
● 实现不太好,缺乏指引。
纵观以上数据发现代码规范的落地的确是一个复杂的问题,既有组织层面上对代码规范重要性、必要性、一致性认知的缺失,也有缺乏高效可落地的检测工具,另外对新人组织宣贯的缺失也是问题。那就需要从组织层面、工具层面、培训层面抽丝剥茧的来逐层将问题个个击破,确保规范的有效,准确落地执行。

二、 代码规范落地实践

2.1. 组织建设

为保证规范落地的准确性和有效性,建议以图2 组织形式组织角色。


● 技术委员会,建议系统架构师,技术带头人,技术经理参与,负责规范、规则梳理、评审、引入已经新增规范的代码编写。是规则的制定者、是仲裁。
● 执行小组,建议QA、PMO、QC人员参与,负责项目数据的整理,问题的跟踪、改进效果展示,反馈问题的收集。阶段性对引进的新规范,有争议规范以及争议问题的评审。阶段性更新代码编码规范,是此项活动的裁判员。
● 项目接口人,项目接入,项目构建,扫描结果分析、修正,以及争议问题反馈。项目成员是此项活动的主体即运动员。
因为专业的事必须交给专业的人来做,代码规范的制定应该由在一线摸爬滚打很多年的程序员主导,由多人参与共同制定,技术委员会可以是一个虚拟的组织,由一线的开发经理组成,尽量贴近业务。

2.2. 运营思路

在运营过程中我们大致规划了三个阶段:
● 规范做成:吸收既有规范,如阿里的JAVA代码规范、规范插件等从严重等级,影响范围维度梳理,将核心的、易识别、争议少的代码规范留存至规则共享平台。但每条规范的通过需由技术委员会评审通过,在组织内部达成一致。此过程是吸收内化的过程,可保障每条规范的有效性。对规范的制定要公开透明,规范内容要细致深入,针对代码规范每一条的详细解释,说清楚为什么要这么制定代码规范,它背后有哪些技术上和工程过程中的故事,说得人心服口服,用技术说服。
● 规范发布:由规则共享平台导出代码规范文档1.0版本,内部宣贯。并通过工具化,服务化的手段将将发布的代码规范可自动化的检测,反馈。通过IDE插件或能力集成的方式将检测的能力集成至pipline当中,形成研发的质量门槛,保障其质量规范的切实执行。此期间可通过质量评分、质量排名等曝光手段推动规范的落地。
● 规范运维:持续运维,纳入质量体系。通过开发反馈,QA统计汇总反馈,技术委员会评审和裁定,落地代码规范,持续监督,定期更新。此阶段在代码规范已经较稳定运行后,依据规则共享平台的反馈对代码规范进行增删,以此保障代码规范的更新迭代。技术更新很快,工程过程中遇到的问题也是层出不穷,因此,代码规范也不会是一招定论的,需要不断地更新、补充、完善,这样才能与时俱进,保持生命力。
通过全员参与形成完备的闭环回路,通过专家评审形成统一认识,通过规范标准的建立达成质量标准的认识。周期性的反馈,不断完善规范的版本,达到代码规范的落地实施。

2.3. 工具平台

仅仅有组织支撑,规范指导是不够的,必须有简单易用的赋能工具,向开发人员提供检测工具或者插件,自动化实现对于代码规范是否执行到位的检测,而不是依靠人工。

2.3.1. SonarQube

以入门简单的SonarQube示例,其实有众多的代码检测工具可供选择如:Flawfinder、Checkstyle或者商业的Coverity作为扫描的引擎,将扫描引擎集成至开发的pipline当中,无感知的提供服务进行代码的分析、度量、反馈。通过不同的对扫描结果进行加工处理,以量化的方式度量代码质量的变化,从而可以方便地对不同规模和种类的工程进行代码质量管理。


通过对代码仓库、扫描引擎、集成工具和规则共享平台进行集成,我们很简单的搭建出面向多角色的一体化框架,从而满足各类需求。
(1)开发者将代码提交到svn工具;
(2)持续集成工具Jenkins自动触发检查代码执行源码扫描、分析;
(3)分析报告传递给SonarQube server进行加工处理;
(4)SonarQube进行处理分析、将数据保存到数据库中;
(5)SonarQube服务将分析结果推送至规则共享平台进行UI展现;
(6)规则共享平台也能够将新的代码扫描规范配置到SonarQube服务;
(7)平台可将扫描结果反馈至相关项目组,提醒及时修改;
(8)项目经理、开发经理、运维经理、测试经理等通过共享平台进行代码相关报表的查看和管理,技术专家可通过平台定制相关规则。

2.3.2. 规则共享平台

通过规则共享平台产出代码规范以及落地实施,规则的产出和准实时监控则是核心。代码规范的评审,监督,统计全部通过规则共享平台完成。
平台实现三个功能:
1、规则评审,对规则录入,审核,实施,废弃。
2、每次代码变更实施后进行规则扫描,并统计起结果,对存量、新增问题进行统计分析。为后续的规范增删打下元数据基础。
3、对项目在时间段内的违规统计。
实现规则的生成,评审,生效,监督,废弃完整生命周期的管理,为全员规则的生成、审核打下基础。
此平台受众为三种角色,开发者,开发经理、技术委员会,他们的所想所得用以下表格梳理:

表1 规则共享平台角色定位


1、面向开发者:每次提交代码后10min内得到代码规范邮件反馈结果。

图4 示例项目代码规范邮件反馈结果

注:BUG即规范冲突点,漏洞为安全规范。链接直接提供修改方案,解决“怎么改”的问题。

图5 检测摘要

图5为单次的检测摘要,可将全量以及增量问题落地。进入详情页后,展示问题的级别(阻断,严重,主要,次要,提示 五级),以及问题的分布。并展示问题位址(文件名以及行数)如图6,以及问题原因,错误示范以及修改方案如图7。


图6 问题定位

图7 规范示例

2、面向项目管理者:周期性统计本组内各开发人员质量数据。


图8 项目维度开发质量统计

3、面向技术委员会:可实现对规范的评审以及管理,以及有效性数据的收集。


图9 代码规范管理

通过以上组织建设、切实运营以及工具平台的建设搭建了代码规范的运营平台,通过全员参与,自动化检测,量化反馈,周期性迭代更新,对规范的产生、落地、更新有一个闭环的管理。彻底解决了传统代码规范不好落地的问题,通过系统解决不愿改,不想改,不会改的问题,如图10。在代码提交阶段,通过代码规范的服务化度量,为代码规范落地实施提供了一种可控手段。并可集成至CI过程中,提供了自动化的服务,在整个CI工具链上丰富了自动化组件,提升测试服务化能力和质量反馈维度。


图10 代码规范落地实践总结

三、 总结

实行良好的代码规范,从长远看最大的受益人往往是团队本身。可能因为繁琐的规范付出了很多额外的工作,但是这些得失,看似无用的东西往往会通过慢慢的积累由量变而到质变,才能感受到其价值所在。
但代码规范的制定、落地是一个辛苦、琐碎、缓慢见效的过程,但也是一个程序员走向成熟的必经之路,唯有你定义的东西能够服众,才能被长久传承下去。
愿我们能在最美好的年华做最有价值事,献给在路上的程序员们。

PS:调研的检测工具检测规范重点,读者可以从各自项目实际情况选择切入点。
Checkstyle:
● Javadoc 注释:检查类及方法的 Javadoc 注释
● 命名约定:检查命名是否符合命名规范
● 标题:检查文件是否以某些行开头
● Import 语句:检查 Import 语句是否符合定义规范
● 代码块大小,即检查类、方法等代码块的行数
● 空白:检查空白符,如 tab,回车符等
● 修饰符:修饰符号的检查,如修饰符的定义顺序
● 块:检查是否有空块或无效块
● 代码问题:检查重复代码,条件判断,魔数等问题
● 类设计:检查类的定义是否符合规范,如构造函数的定义等问题
FindBugs:
● Bad practice 坏的实践:常见代码错误,用于静态代码检查时进行缺陷模式匹配
● Correctness 可能导致错误的代码,如空指针引用等
● 国际化相关问题:如错误的字符串转换
● 可能受到的恶意攻击,如访问权限修饰符的定义等
● 多线程的正确性:如多线程编程时常见的同步,线程调度问题
● 运行时性能问题:如由变量定义,方法调用导致的代码低效问题
PMD:
● 可能的 Bugs:检查潜在代码错误,如空 try/catch/finally/switch 语句
● 未使用代码(Dead code):检查未使用的变量,参数,方法
● 复杂的表达式:检查不必要的 if 语句,可被 while 替代的 for 循环
● 重复的代码:检查重复的代码
● 循环体创建新对象:检查在循环体内实例化新对象
● 资源关闭:检查 Connect,Result,Statement 等资源使用之后是否被关闭掉

参考文献

[1]Sonar

https://blog.sonarsource.com/
[2]Findbugs

http://findbugs.sourceforge.net/
[3]Checkstyle

![]

http://checkstyle.sourceforge.net/
[4]PMD

https://pmd.github.io/

本文转自微信公众号:上交所技术服务

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

3

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广