对于一个软件开发团队,可以通过哪些代码质量指标和扫描方法让团队产出规范、安全、高质量的代码?让开发团队运行的安全、透明、可靠?本文总结了其中一些实践和工具,包含常见代码质量扫描工具、代码质量指标、第三方依赖管理、安全运维等几个方面,主要适用于 Java/JavaScript 技术栈的 web 项目,希望对于想要规范化自己的项目的 Tech Lead 有所帮助。
代码扫描和常见质量指标
“祸患常积于忽微”,往往一些奇怪的 bug 都是一些不规范的小问题造成的。德国飞机涡轮机的发明者帕布斯·海恩提出的一个在航空界关于飞行安全的法则,法则指出: 每一起严重事故的背后,必然有 29 次轻微事故和 300 起未遂先兆以及 1000 起事故隐患。应用于软件开发中,如果项目中代码混乱不堪,必然会在某个时候最终爆发大量的问题。
这里整理了一些常见的扫描工具和代码质量指标,可以在搭建项目基础设施时引入,用于自动化的检查代码中潜在的问题,达到控制代码产出质量的目的。
扫描工具
(1) checkstyle:checkstyle 是常用于 java 项目的扫描工具,检查源代码是否与代码规范相符,检查项目主要包括:Javadoc 注释、imports、过长的类和方法、空格、重复文件、圈复杂度等,默认使用 sun 的代码规则,也可以配置自定义的代码规则,例如阿里就发布了相应的检查规则。
(2) findbugs:通过 Bug Patterns 的概念,寻找代码中可能出现的 bug,检查项目主要包括:不良编程习惯导致的问题、性能问题、安全问题、线程问题等。例如,应使用 equals 判断相等,而不是 “ =” 操作符、流需要关闭、线程资源需要释放等问题。findbugs 的模式库对编程经验也有较好的提升作用。还可以导入和编写自己的 Bug Patterns 完善检查机制。
(3) simian:simian 是一个用于检查重复和相似代码的工具,它的重复检查类似于论文查重,会提示一定的相似度。可以单独运行,也可以作为 checkstyle 插件来使用,相对来来说比较小众。
(4) pmd:pmd 是一款跨语言的通用静态扫描工具,具备一部分 checkstyle、findbugs 的功能,不再赘述。
(5) ESlint/TSlint:前端界的 checkstyle , TSlint 设计用来做 TypeScript 类型检查,ESlint 作为代码风格检查工具。不过现在 ESlint 也提供了TypeScript 类型检查功能,基本上 ESlint 能整合这两个功能。由于性能问题, TypeScript 也采用了 ESLint 作为 TSlint替代的检查工具。
(6) SonarQube:SonarQube 是一款用于代码质量管理的开源工具,它主要用于管理源代码的质量。SonarQube 和上面的工具不太一样,SonarQube 设计目的是提供一个平台,通过插件的方式提供对各个语言进行支持,也可以和 checkstyle、pmd、simian 等工具进行集成。SonarQube 一般需要单独部署成一个服务,提供数据库,可以记录扫描结果等信息。
(7) npm audit:npm audit 是 npm 6 之后的版本 自带的一个前端安全扫描工具,可以扫描 npm 依赖中的潜在的漏洞威胁。这些引入的漏洞可能威胁用户开发的机,另外也可能被带入 bundle 文件发布到线上,带来安全问题。目前 npm audit 会在 npm install 完成后自动执行,需要留意安全威胁报告。
(8) Fortify SCA:Fortify SCA(Source Code Analyzer) 是一款非常优秀的代码安全扫描工具,用于分析代码中潜在的安全问题。通过调用语言的编译器或者解释器把代码(Java、C、C++等源代码)转换成一种中间媒体文件 NST(Normal Syntax Trcc),然后通过模式匹配相关的方式抓取存在于漏洞库中的漏洞。例如,上传的文件没有做检查等 XSS 攻击。
(9) OWASP Dependency-Track:开放式 Web 应用程序安全项目(OWASP)是一个非营利组织,提供了很多安全标准、数据库、社区和培训。其中一个工具就是 OWASP Dependency-Track,可以对第三方依赖包中的知名漏洞进行检查,扫描结果受到漏洞数据库的更新影响。
(10) archunit 架构规范检查:前面的检查是代码层面,archunit 可以用于代码架构检查,可以定义规则检查每个包中的实现是否符合规范。例如,controller 包中的类不能实现 service 的接口,repository 下的类必须实现 Repository 接口。通过 archunit 可以减少 codereview 的工作量,避免项目的结构被破坏。
统计工具
sloccount、sourcemointor 这两个工具可以用于统计代码数量,包括行数、文件数、注释等。除了在项目中扫描 bug 之外,配置代码统计工具可以对项目有一个整体的认知。其他的扫描工具还很多,例如 coverity、codemars、binscope、synk、appscan、retire.js 等工具,不再一一列举。
最佳搭配
这几款工具之间的功能有所重叠,在实际工作中,我们可以根据上面推荐的关注的点,重点清除这些问题。这些扫描工具全部用上除了会带来团队压力和维护成本之外,代码质量不会随着引入的插件增多。除开有质量团队的大厂提供这些扫描平台外,敏捷团队往往不会太大,团队持续关注一个精简的扫描组合更好。
Java 后端:
前端:
安全:
为什么不用 SonarQube 呢,SonarQube 是一个非常优秀的代码质量开放平台,需要单独的配置安装,需要花费额外的时间维护,对于小团队来说成本较高,如果有专门的质量团队可以考虑维护一套。
常用代码质量指标参考
第三方依赖规范化
软件开发过程中,不可避免的需要引入第三方或者开源软件包作为库或者框架引入。“第三方” 其实不是一个软件工程术语,现今在软件行业里面的理解是:第一方为自研的软件,第二方为内部发布的软件,第三方为从社区或者外部商业途径引入的软件包。对于个人开发者而言,面向“搜索引擎”编程往往将来源不明的代码片段和程序包引入到项目中。对于企业来说,考虑到的不仅仅是功能是否能实现,还要考虑引入时带来的成本和问题,例如是否需要授权、开源协议是否合理、是否会带来安全威胁。企业对于第三方依赖的引入分为几种情况:
引入第三方依赖需要充分考虑,尽可能最小成本的引入。在一个 React 的前端项目中,有不熟悉的工程师,为了使用一个简单的手风琴效果,引入了整套 bootstrap。不仅破坏了使用 React 的最佳实践,而且让输出的 bundle 文件大小激增数倍,造成首屏加载的性能问题。
常见商业友好的开源协议
商业用户常用的开源协议实际上只有6种左右,即 LGPL、Mozilla、GPL、BSD、MIT、Apache,另外还有极其宽松的 The Unlicense,但采用的开源软件不多。GitHub 提供了一个 license 清单的列表 https://choosealicense.com/licenses/,我根据开源协议的宽松程度,整理了一个列表,方便查看:
几乎所有的开源协议有一个共同的注意事项:采用该开源协议的软件项目,不提供任何责任转移和质量保证。也就是说采用开源软件造成的法律问题和开源项目无关,另外需要使用者承担因质量问题造成的所有后果。另外,除了引入的程序包之外,字体、图片、特效音、手册等媒体资源也算广义上的“软件”需要考虑开源协议和使用场景。
第三方依赖管理
对项目中出现的任何第三方依赖有效的管理有非常重要的意义,通过扫描工具,识别出项目中是否有源码、jar包、二进制文件是否来源于某个开源项目。任何的第三方软件需要申请入库管理(内部其他团队申请通过可以直接使用),质量团队对申请的软件进行评估:
质量团队根据上面的一些条件,决定出申请的软件能否在项目中使用,允许被采用的软件会定义出优选级别,优先推荐团队使用较为优选的软件,并对项目整体的优选率有一定要求。如果项目中出现了无法识别的二进制文件、非约定目录下的代码片段,需要报备。通过良好的依赖管理和规范化,能减少不良第三方依赖的引入,让软件项目透明、可信。一些商业公司提供这些完整的服务,例如 fossid、blackduck、code-climate 等。
运维安全
大的软件公司,往往有一堆流程和要求。虽然一线开发对堡垒机、防火墙、各种安全规范显得不耐烦,但这些安全措施也在保护开发者。
1. 防火墙用于环境隔离
往往开发者理解的防火墙用于防止网络入侵、审计、入侵检测等功能,除此之外,防火墙还可以用于各个环境的隔离。一般来说,企业对于生产环境的数据控制比较严格,不会将生产环境的权限交给团队所有开发者,但网络连接有可能疏漏。曾经出现过一次线上事故,由于配置文件错误,将原本应该连接到测试的数据库连接到了生产环境,造成大量脏数据写入。如果通过防火墙规则对各个环境进行隔离,这类问题将不会出现。另外也可以设计 DMZ 区,将面向用户侧的网关部署到 DMZ 区,仅仅开放必要的端口给网关,实现内外网的物理隔离。同时,对整个系统的防火墙策略应该清晰地记录,否则在做大的基础设施更新时,梳理出所有的防火墙策略,是一件比较困难的事情。
2. 凭据管理
项目中会用到大量的凭据,例如数据库、第三方系统对接的 key,使用明文不是一件好事。理想的情况下,对项目中所有的密码信息进行掩盖(mask),避免 CI、日志中敏感信息的泄露。有很多种方法可以掩盖项目中的密码信息:
另外,建议不要用任何个人凭据用作系统对接,应该使用一个公共的应用凭据。
3. 堡垒机
一般来说我们管理服务器,所有的运维操作需要通过堡垒机进行操作。开放 22 等高危端口,允许开发者直接登录到服务器是一种不安全的做法。堡垒机,通俗的来说是跳板机 + 监控。最初使用的跳板机配置了两张网卡,用于连接开发环境和生产环境,并没有监控功能。在此基础上,堡垒机增加了统一运维管理的功能,往往需要两步验证(SMS 或 Email),并对所有的操作进行记录和监控。在需要团队参与运维工作的场景中,非常有必要部署一套堡垒机服务,并使用 LDAP 对接到团队成员的 ID 上,便于集中运维管理。
4. 定期对系统软件扫描
Linux 系统往往有云厂商推送安全补丁和风险提示,但是安装到服务器上的软件,例如 JDK、nodejs,需要自己检查安全问题。因此需要在系统中安装并定期运行 CVEs 检查并及时更新。有一款 cvechecker 可以帮助运维人员,编写一个脚本定期运行 cvechecker 检查系统中已知的软件是否存在 CVEs 漏洞,并提醒开发者及时更新。
写在后面
刚开始工作时候,喜欢动态的、灵活的编程语言,讨厌的死板的、套路化的编程语言,然而需要很长一段时间,才能意识到 “约束是程序员的朋友”。对一些安全知识了解的来源大多来自修复 SonarQube 的经历,使用 findbugs 也让我对 Java 基础认识的更加深刻。
类似的,在使用一些框架、平台的时候往往存在大量的限制,有时候开发者难以意识到 “限制” 正是框架、平台的作者 “保护” 应用开发者的一种方式。有一些开发者以 Hack 框架、平台为乐,但是这样会带来潜在的隐患,在用户量上来之后负面效应表现的尤为明显。
项目的规范化对于 Tech Lead来说可以减少程序的运行事故和 codereview 时间,对于团队来说也许可以少加班吧。
【本文是专栏作者“ThoughtWorks”的原创稿件,微信公众号:思特沃克,转载请联系原作者】
戳这里,看该作者更多好文
本文题目:如何产出规范、安全、高质量的代码?
本文来源:http://www.mswzjz.cn/qtweb/news35/470285.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能