好的代码一定是整洁的,并且能够帮助阅读的人快速理解和定位。好的代码可以加快应用的开发迭代速度,不必花过多的时间来修复 bug 和完善代码。好的代码不但能够使得新的项目成员更容易加入项目,同时方便项目组成员快速做好 Back up。好的代码便于促进团队间交流合作提升开发效率。

        在日常研发过程中,我们通常面临的代码资产问题主要分为两大类:代码质量问题和代码安全漏洞。

一、代码质量问题

        代码质量其实是一个老生常谈的话题,但问题是大家都知道它很重要,却又不知道如何去提升和维护这一团队的共同财产。一方面开发人员可能为了功能及时上线,疏忽了对质量的把控,另一方面开发人员编码习惯和程序理解风格各异。

        长期下来代码质量下降通常会自成因果,因为业务压力大而趋于下降,又因此开发效率下降,进一步加大业务压力,导致恶性循环。

        当下较常用的鉴定代码质量的评价标准,包括:编码规范、可读性、可维护性、重复度及可测试性。

1、编码规范

        主要包含是否遵守了最佳实践和团队编码规范,是否包含可能出问题的代码,以及可能存在安全的漏洞。编码规范有助于提高团队内协助的效率以及代码的可维护性。

2、可读性

        Code Review 是一个很好的测验代码可读性的手段。如果你的同事可以轻松地读懂你写的代码,那说明你的代码可读性很好;反之则说明你的代码可读性有待提高了。遵守编码规范也能让我们写出可读性更好的代码。

3、可维护性

        代码的可维护性是由很多因素协同作用的结果。代码的可读性好、简洁、可扩展性好,就会使得代码易维护;更细化地讲,如果代码分层清晰、模块化好、高内聚低耦合、遵从基于接口而非实现编程的设计原则等等,那就可能意味着代码易维护。除此之外,代码的易维护性还跟项目代码量的多少、业务的复杂程度、利用到的技术的复杂程度、文档是否全面等诸多因素有关。

4、重复度

        遵守 Don’t Repeat Yourself 原则,尽量减少重复代码的编写,复用已有的代码。对项目定期进行代码重复度检测是一个很有意义的事,可以帮助开发人员发现冗余代码,进行代码抽象和重构。重复的代码一旦出错,意味着加倍的工作量和持续的不可控。如果代码中有大量的重复代码,就要考虑将重复的代码提取出来,封装成公共的方法或者组件。

5、可测试性

        代码可测试性的好坏,同样可以反应代码质量的好坏。代码的可测试性差,比较难写单元测试,那基本上就能说明代码设计得有问题。

        除此之外还有很多代码质量评价标准。我们需要一些取舍,选取部分大家有共识的规则定义团队好的代码标准。

二、代码安全问题

        安全类问题往往隐藏在缺乏安全意识的编码逻辑和未经检测或维护的开源依赖组件中,难以在日常开发和代码评审中被及时察觉。

代码安全问题也可以分两个方面进行分析:

  • 编码安全问题,即:安全规范类问题,通过避免不符合规范的代码进入企业代码库,减少隐私数据泄露、注入类风险、安全策略漏洞的出现。
  • 依赖安全问题,即:开源依赖三方组件引入的安全漏洞。根据 Synopsys 2020 开源安全报告显示,99%以上的组织使用了开源技术。使用开源组件本身带来的技术交流和站在巨人肩膀上协作、降低开发成本、加快迭代周期、提高软件质量等优势已经不必赘述,但是,开源软件带来一系列便利的同时,也暗藏大量安全风险,据审计,75%的代码库存在安全漏洞,其中 49%包含高危问题,另外 82%的代码库仍在使用超过 4 年的 outdated 组件。

        代码安全类问题,一方面也需要进行准入性检查,根据业务场景和规范配置安全编码规范检测和卡点。另一方面需要定期维护,对于新爆发出的安全漏洞进行及时察觉并修复。

三、代码质量审核和管理工具(开源版)

        如今,代码质量分析和审核已成为每个企业的基本流程。随着开源代码库使用的增加,安全性和代码质量对于构建高质量软件至关重要。不良的代码不仅会影响代码的可维护性,而且还会在某些情况下影响其性能。此外,更好的代码质量还有助于企业将来减少维护和降低成本。幸运的是,有很多审核和管理代码的工具,为开发者和程序员提供了发现代码问题的解决方案。

3.1 SonarLint & SonarQube

        SonarQube是市场上很受欢迎的代码质量和安全性分析工具。它在开源社区的支持下,目前可以分析和产生对超过25种编程语言的输出,这比市场上大多数工具都要高。它具有免费的社区版本和其他付费版本。

        SonarQube为程序员提供了一个平台,可以分析27多种不同编程语言中的代码,并帮助您提高性能和检测安全漏洞。它由SonarSource的团队开发,对社区免费开源。SonarQube可以添加到您的CI/CD管道中,或者与您选择的代码库托管平台集成,从而帮助执行连续的代码分析。        

        利用SonarQube的主要好处是可以帮助你确保代码在合并之前达到预期的质量!

优点:

  • 只需一行命令即可轻松集成到CI/CD管道中;
  • 多语言支持;
  • 可以集成到Maven和Gradle构建周期中;
  • 检查几乎所有内容,如代码质量,格式,变量声明,异常处理等;
  • 执行安全分析。

缺点:

  • 不会通知用户何时完成耗时的扫描。

官网:https://www.sonarqube.org/

        必须要指出 SonarQube 是开源的代码质量管理平台,以 web 页面形式(即Sonar Dashboard)可视化形式检查代码质量;SonarLint 是 SonarQube 提供的插件,可以安装在各个 IDE 工具。
        后来者居上,SonarQube是一个集大成者,允许配置安装插件,比如Findbugs, PMD 和 CheckStyle,基于这些插件的代码质量检查规则多达上千条,已经可以覆盖代码质量的绝大多数方面,更新版本的功能更多。


Sonar 可以从七个维度检测代码质量:

  1. 代码规则——sonar可以通过PMD,CheckStyle,Findbugs等等代码规则检测工具规范代码编写;
  2. 潜在的缺陷——通过PMD,CheckStyle,Findbugs 等代码规则检测工具检测出潜在的缺陷;
  3. 复杂度——无论对于类还是方法,都不宜过长,长意味着复杂,问题丛生……。
  4. 重复——sonar会检查重复片段,此时需要重构并提取共有逻辑;
  5. 注释不足或者过多——关键的代码片段不能没有注释,注释得简洁有意义,且需要及时更新;
  6. 单元测试——sonar可以很方便地统计并展示单元测试覆盖率;
  7. 架构与设计——通过sonar可以找出循环,展示包与包、类与类之间相互依赖关系,可以检测自定义的架构规则 通过sonar可以管理第三方的jar包,可以利用LCOM4检测单个任务规则的应用情况, 检测耦合。

特性:

  • 通过插件扩展
    支持新的编程语言、添加规则引擎、计算更复杂的度量指标,这些都可以借助强大的插件扩展机制。通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具,比如pmd-cpd、check-style、find-bugs、Jenkins。通过不同的插件对这些结果进行再加工处理,通过量化的方式度量代码质量的变化,从而可以方便地对不同规模和种类的工程进行代码质量管理。
  • 支持多种编程语言
    借助插件,支持各种主流编程语言;
  • 集成CI
    同时 Sonar 还对大量的持续集成工具提供接口支持,可以很方便地在持续集成中使用 Sonar
  • 代码质量周边
    提供插件,规则、告警、例外……都可以在线配置。通过自己的数据库,SonarQube不仅仅是展示各项指标的综合结果,同时也结合历史质量数据。
  • 国际化
    对国际化以及报告文档化也有良好的支持。

IDEA 安装插件 Sonar Lint

        安装 Sonar Lint 插件需要重启,然后打开other setting——SolarLint——General Settings,输入sonarqube的地址,一般公司会搭建内网平台,在 Server URL 里面添加这个地址,按需输入用户名/密码,测试连接,连接成功即可使用。

sonar平台搭建

        非常类似于Jenkins,sonar提供war包,下载解压,配置一下数据库(默认MySQL,本地或者远程都行),然后启动脚本(bat或sh)。

3.2 PMD

        代码库一直在持续更新的代码质量检查工具,通过静态分析获知代码错误,即无需运行Java程序的情况下就报告错误。提供各大 IDE 插件,提供 maven-pmd-pluginmaven插件。最新版的 Java 语言质量检查规则

        PMD是基于源代码分析,主要面向安全编码规则,如“避免声明同名变量”,包括类风格、类型使用等等,具备一定的数据流分析和路径分析能力。

        PMD支持用户自定义规则。下面列出一些检查规则:

  • If、While、IfElse、For表达式必须使用{},无论有多少语句;
  • 如果方法返回boolean,那么注意避免不必要的if…then…else语句;
  • 避免if语句嵌套过深(降低代码可读性);
    解决办法:建议if嵌套不要超过2层。使用工具方法封装更多的if语句或者把嵌套的if表达式放到同一个层次中;
  • 忽略大小写进行字符串比较时,使用String.equalsIgnoreCase,不要使用String.toLowerCase。前者有更好的性能,而且还可以避免后者带来的本地化问题;
  • 避免方法级的同步,块级别的同步可以确保内含真正需要同步的代码;
  • 使用集合类的isEmpty方法;
    java.util.Collection类的isEmpty方法提供判断一个集合类是否包含元素。不要是使用size()和0比较来重复类库已经提供的方法。原则:尽量复用,充分利用已有的资源,不要重复造轮子。
  • 没有使用的就去掉,保持代码的干净、整洁,包括:没有使用的私有成员、本地变量、私有方法、方法参数(参数定义,但方法内没有使用此参数)
  • 构建StringBuffer或StringBuilder时,如果知道长度,请指定,这样性能更好。不指定,则默认长度是16,这样当长度不够时,就会有扩容的动作。
  • 如果本地变量只被赋值一次,或者方法参数从来不会被重新赋值,可以把它声明为Final;
  • 如果想由数组构建List,请使用Arrays.asList;
  • 数组复制,请使用System.arraycopy,别用循环;
  • "" + 123 的方式把数字转换为String,不够高效;
  • 避免代码中出现各种”空”的语句:空Catch,If,while,try,finally,switch,Synchronized,static块;
  • 重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs;
  • 循环体创建新对象:尽量不要再for或while循环体内实例化一个新对象;
  • 资源关闭:Connect,Result,Statement等使用之后确保关闭掉;
  • ...

PMD特点

1、与其他分析工具不同的是,PMD通过静态分析获知代码错误。也就是说,在不运行Java程序的情况下报告错误。
2、PMD附带了许多可以直接使用的规则,利用这些规则可以找出Java源程序的许多问题
3、PMD规则是可以定制的: 可用的规则并不仅限于内置规则,用户还可以自己定义规则,检查Java代码是否符合某些特定的编码规范。 例如可以通过编写 Java 代码并重新编译 PDM,或者更简单些,编写 XPath 表达式,它会针对每个 Java 类的抽象语法树进行处理,可以编写一个规则,找出所有创建Thread和Socket对象的操作。

4、同时,PMD已经与JDeveloper、Eclipse、jEdit、JBuilder、 BlueJ、CodeGuide、NetBeans、Sun JavaStudio Enterprise/Creator、IntelliJ IDEA、TextPad、Maven、Ant、Gel、JCreator以及Emacs集成在一起。

基本使用

          命令行方式:java -jar pmd-6.8.0.jar /your_project/src text rulesets/unusedcode.xml,更详细的命令行参数使用-help查看即可得知。
        idea集成pmd,搜索插件安装即可。

工作原理

        PMD的核心是JavaCC解析器生成器。PMD结合运用JavaCC和EBNF(扩展巴科斯-诺尔范式,ExtendedBackus-Naur Formal)语法,再加上JJTree,把Java源代码解析成抽象语法树(AST,Abstract SyntaxTree)。不过,为了让解析器承认这些普通的文本是合法的Java代码,它们必须符合某种特定的结构要求。这种结构可以用一种称为EBNF的句法元语言表示,通常称为“语法”(Grammar)。JavaCC根据语法要求生成解析器,这个解析器就可以用于解析用Java编程语言编写的程序。

        实际运行中的PMD还要经过JJTree的一次转换。JJTree是一个JavaCC的插件,通过AST扩充JavaCC生成的解析器。AST是一个Java符号流之上的语义层。有了JJTree,语法分析的结果不再是System, ., out, ., .println之类的符号序列,而是一个由对象构成的树型层次结构。

3.3 Kritika

        Kritika.io是一款出色的在线代码分析工具,可直接为你分析公共和私有存储库。

        它负责为代码标准冲突,安全威胁,测试范围和编码逻辑的复杂性逐步分析代码。它可以与Github轻松集成,以直接在存储库中显示代码质量统计信息。

优点:

  • 免费进行公共存储库扫描
  • 私有存储库的付费云服务
  • 具有更多集成功能的本地部署
  • 它支持超过12种编程语言和文本文件。

3.4 FindBugs

官网
最后一次更新是06 March, 2015,不算太过时。

简介

        FindBugs是一个开源的java byte code静态分析工具,检测出Java程序中上百种潜在的不同类型的错误,是一个基于LGPL开源协议,无需运行就能对代码进行分析的工具。不注重style及format,注重检测真正的bug及潜在的性能问题,尤其注意尽可能抑制误检测(false positives)的发生。除了作为单独的组件安装,还可以集成IDE,以及maven。其检测输出结果可以是XML或文本形式的。支持自定义配置检查规则(做哪些检查,不做哪些检查),校验规则(用户自定义特定的bug模式需要继承它的接口,编写自己的校验类)。

规则

        FindBugs检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。根据最新的页面bugDescriptions,自带88种Bad practice,149种Correntness,3种Experimental,2种Internationalization,18种Malicious code vulnerability,46种Multithreaded correntness,29种Performance,11种Security,80种Dodgy code。

        这个页面能看到很多缩写,缩写的意义,以及不规范的和建议的规范的代码的解释。多看几遍,对于规范自己的coding style非常有帮助。

        IDEA安装FindBugs非常容易。安装完之后,可能需要设置提高检查的级别,因为可能检查规则过于严格。

特点

1、FindBugs主要着眼于寻找代码中的缺陷,这就与其他类似工具有些区别了,直接操作类文件(class文件)而不是源代码。
2、FindBugs可以通过命令行、各种构建工具(如Ant、Maven等)、独立的Swing GUI或是以Eclipse和NetBeans IDE插件的方式来运行。                
3、FindBugs输出结果既可以是XML的,也可以是文本形式的。
4、开发者可以通过多种方式来使用FindBugs,最常见的是在新编写模块的代码分析以及对现有代码进行更大范围的分析。   
5、不注重style及format,注重检测真正的bug及潜在的性能问题,尤其注意了尽可能抑制误检测(false positives)的发生。

3.5 checkstyle

        CheckStyle检查代码是否符合制定的规范。CheckStyle 检查是基于源码的,所以不需要编译,执行速度快。
主要流程

  1. 对Java文件进行词法语法分析,生成语法树。
  2. 载入配置文件(checkstyle-metadata.xml以及自定义的配置文件)register check事件。
  3. 按照深度优先遍历对语法树进行解析,按照注册的事件,在到达某些节点( AST ) 时进行style检查(AST,A child-Sibling Tree,是语法树中的某个节点,其类型在TokenTypes类中定义。)
  4. 自定义Style的检查,就是在第二步设定的。实现com.puppycrawl.tools.checkstyle.api.Check类,重载其中的两个方法:public int[] getDefaultTokens()public void visitToken(DetailAST ast)。这两个方法的含义为,在遍历语法树的过程中,每当到达getDefaultTokens函数所返回的AST类型,程序就进入visitToken进行具体的检查和分析,即真正的分析检查过程是在visitToken中实现的。

        CheckStyle有针对不同IDE和构建工具的各种插件,如 maven-checkstyle-plugin 插件,其简单的参考配置:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-checkstyle-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
    	<!--内置4种规范:config/sun_checks.xml、config/maven_checks.xml、config/turbine_checks.xml、config/avalon_checks.xml、其中sun_checks.xml为默认值。修改默认配置-->
        <configLocation>config/maven_checks.xml</configLocation>
        <!--启用自定义规范文件-->
        <!--<configLocation>${basedir}/src/config/custom_checkstyle.xml</configLocation>-->
    </configuration>
    <executions>
        <execution>
            <id>checkstyle</id>
            <phase>validate</phase>
            <goals>
                <goal>check</goal>
            </goals>
            <configuration>
                <failOnViolation>true</failOnViolation>
            </configuration>
        </execution>
    </executions>
</plugin>

        定义在maven lifecycle的validate阶段执行check task,并且如果发现有违反标准的情况就会fail当前的build。运行checkstyle检查:mvn checkstyle:checkstyle

跳过对指定文件的某些检查
        方法一:suppression:忽略指定文件的问题检查,不推荐;
        方法二:新建一个checkstyle-suppressions.xml文件,增加suppressions配置项:

<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.0//EN" "http://www.puppycrawl.com/dtds/suppressions_1_0.dtd">
<suppressions>
    <suppress checks="LineLengthCheck" files="SessionMessageSource.java"/>
</suppressions>

<suppressionsLocation>${basedir}/src/config/checkstyle-suppressions.xml</suppressionsLocation>
        然后在配置文件里面可以定义一系列可用的模块,每一个模块提供严格程度(强制的,可选的…)可配置的检查规则。规则可以触发通知(notification),警告(warning)和错误(error)。
附:google-checkstyle

特点:

  1. 它可以有效的帮助我们检视代码以便更好的遵循代码编写标准,特别适用于小组开发时彼此间的样式规范和统一。
  2. Checkstyle提供高可配置性,以便适用于各种代码规范,所以除了使用它提供的几种常见标准之外,你也可以定制自己的标准。
  3. Checkstyle提供支持大多数常见IDE的插件,大部分插件中就含有最新的Checkstyle。
  4. Checkstyle可以检查代码的很多方面,从传统观点看,它主要是用来检查代码层面的,自从第三版以后,它的内部架构作了重大改变,很多其它意图的检测加了进来,现在Checkstyle可以检查像类设计的问题,重复代码,如锁的双重检查的bug模式。

3.6 DeepScan

        DeepScan擅长扫描Javascript代码存储库。它能够处理几乎所有javascript框架的动态代码质量检查。

        它为你提供了一个出色的仪表板,可以在一处管理和维护所有项目以及代码质量等级。使用Deepscan的主要好处包括:

  • 提供随时间扫描数据的图形视图
  • 有助于分析和跟踪代码管理过程的进展情况
  • 对于在单个平台上进行组织范围的代码质量审核很有用
  • 自动扫描存储库
  • 可在云和本地上运行

3.7 Klocwork

        Klocwork可以对几乎任何大小的项目执行静态代码分析。使用Klocwork的主要好处是它可以轻松地与Visual Studio Code IDE,Eclipse,IntelliJ等集成。这使开发人员更容易使用Klocwork。此外,它也可以集成到CI/CD管道中,以确保交付前的代码质量。它支持C,C#,C ++和Java。

3.8 CodeSonar

        CodeSonar是一种统计代码分析工具,可以从计算角度分析代码。它能够从你的代码中开发模型,分析它们的潜在执行威胁,例如锁死,内存溢出,空指针,数据泄漏以及可能难以捕获的许多此类程序错误。

  • 它完成的代码扫描比其他代码更深入。
  • 能够检测到比其他工具多3-5倍的缺陷
  • 它可以构建自己的函数调用图,以分析完整的代码模型并提供有关质量的输出。

3.9 JArchitect

        JArchitect主要致力于Java语言中的代码分析。JArchitect是用于分析的最详尽的Java代码分析工具。JArchitect被三星,英特尔,LG,IBM,谷歌等巨头使用,这也从侧面印证了该工具的出色程度。

        JArchitect是一款静态分析工具,使用一种基于Linq(CQLinq)的代码查询语言,像查询数据库那样来查询代码。最新版v2019.1下载地址,可以把许多其他静态分析工具的输出结果包含进来,然后使用CQLinq做查询,提供CI/CD工具集成功能,提供报表功能。付费工具,功能很强大。


简单使用:
        解压缩,双击VisualJArchitect.exe,新建工程,选择一个想要被分析的项目,然后点击开始分析即可。

        从分析结果面板可见其功能强大。

CQLinq:
        类似SQL语法,有智能提示,并且给出近乎实时的语法检查和查询结果;

3.10 Bandit

        Bandit是一个Python安全漏洞扫描工具,可扫描python软件包中的安全漏洞。它是数据科学家和AI专家中流行的工具,用于构建符合组织标准的代码。Bandit可用于命令行界面。

3.11 Code Climate

        Code Climate是一种分析工具,对强调质量的组织非常有用,它支持十多种语言。Code Climate提供两种不同的产品:

(1)Velocity:识别代码中的逻辑缺陷和不良设计模式。它提供了经过良好分析的代码质量可视化,并有助于解析代码质量。速度功能侧重于提高代码的功能质量。

(2)Quality:在格式,未使用的导入,变量和单元测试覆盖率方面,主要关注代码质量。这是一个自动化工具,可以自动处理所有拉取请求。这样可以确保合并之前的质量。

3.12 Crucible

        来自Atlassian公司的Crucible是用于管理代码质量的有趣的协作工具。Crucible允许与流行的工具(例如Jira,Github,Confluence)以及CI/CD工具(例如Jenkins或AWS CodePipeline)集成。Crucible的一些特征包括以下内容:

  • 查看和协作代码
  • 自动触发代码扫描,并在所需工具中查看报告
  • 在一处跟踪完整的代码审查周期

3.13 Fortify

        Micro Focus的Fortify专注于扫描代码库中的安全漏洞。它着眼于已知的安全漏洞以及可能存在问题的任何恶意软件或损坏文件的存在。一些不错的功能包括:

  • 自动扫描代码
  • 涵盖几乎所有编程语言
  • 提供解决漏洞的建议
  • 提供丰富的代码分析,以帮助更快地解决问题
  • 与流行的CI/CD工具轻松集成

3.14 Codecov

        Codecov是用于管理代码库以及使用单个实用程序进行构建的综合工具。它分析推送的代码,执行所需的检查,并在需要时自动合并它们。下面列出了一些其他功能:

  • 单行命令可以扫描,分析,生成报告并将其合并
  • 可与几乎所有流行的CI/CD工具集成
  • 支持30多种编程语言
  • 将报告集成到Github存储库中,以简化代码审查

3.15 Hammurapi

        Hammurapi它是一个开源的代码审查/评审(review)工具。它可以帮助改进Java代码的质量。它可以基于一套设计规范来分析代码库。当它碰到违反规范的地方,会在报告中标识。就像Checkstyle一样,它与Ant无缝集成并且由基于XML配置文件来驱动。

特点

1、Hammurapi是用来强制代码设计规范的。

2、Hammurapi是一个遵循设计的工具,提供了自动而且一致的方式来实现设计规范,因此使代码评审更加有效而轻松。

工作机制

        Hammurapi这样的代码分析工具都带有语言分析器。语言分析器是一种输入语言代码并输出抽象语法树的工具。这个树上的节点代表语言标识。例如,考虑一下简单的算术表达式:3+4. 语言分析器会解析他成为一个语法树。在这个树中,节点+代表操作符标识。节点3和4是操作数标识。

        Hammurapi使用ANTLR(另一个语言识别工具)作为语言分析器。然而ANTLR API是相当底层的。为改善可用性,Hammurapi使用另一个API,基于ANTLR 的JSEL(Java源程序工程类库),来访问抽象语法树。 一旦树构建完成,一种树遍历算法就被用来访问树中每一个节点。每次访问到一个节点,一种回调机制(Visitor模式)被用来提示相应的检查器。在这些回调方法中,检查器收集相关的信息来确定是否有违反规范的地方存在。

3.16 Lint4j

        Lint4J是一个针对Java的源代码分析工具,它可以对Java源码和字节码进行静态分析,判断其中是否存在死锁、性能问题或者伸缩性问题。它可以集成到任何IDE种或构建系统。
特点

1、检测代码语法规则
2、潜在的bug
3、检测编码模式对代码可读性及大小的影响
4、检测是否违反EJB规范

3.17 JDepend

        JDepend一个开放源代码的可以用来评价Java程序质量的优秀工具,它遍历Java class的文件目录,以Java包(package)为单位,为每一个包/类自动生成 包的依赖程度,稳定性,可靠度等的评价报告,根据这些报告,我们可以得到包或类之间的依赖关系,并分析出包的稳定程度,抽象程度,是否存在循环依耐关系等 。可以根据JDepend给出的报告数据,分析出我们的包是否是可靠的,稳定的,健壮的包,是否符合面向对象的设计原则。

特点

1、评价设计质量
2、翻转依赖性
3、支持并行开发和极限编程
4、独立的发布模块
5、识别package的循环依赖

Depend生成的Java包的质量评价报告主要包括:    

1、Number of Classes and Interfaces:实现类与抽象接口的数目
2、Abstractness (A):包的抽象度。指一个包内包含的抽象类或接口占整个包中的类的比重。
3、Afferent Couplings (Ca):向心耦合。依赖该包(包含的类)的外部包(类)的数目(i.e. incoming dependencies),该数值越大,说明该包的担当的职责越大,也就越稳定。
4、Efferent Couplings (Ce):离心耦合。被该包依赖的外部包的数目(i.e. outgoing dependencies),该数值越大, 说明该包越不独立(因为依赖了别的包),也越不稳定。
5、Instability (I):衡量一个包的不稳定程度。I=Ce/(Ce+Ca)。它的值处于[0,1]之间。I=0时说明包是最稳定的,反之I=1则说明包极不稳定。
6、Distance from the Main Sequence (D): 该指标主要用来评价包的抽象程度与稳定程度的平衡关系,它可以用二维直线图 A + I = 1 来表示。
7、Package Dependency Cycles:包的循环依赖度。

3.18 BEAM

        IBM Checking Tool for Bugs Errors and Mistakes(简称BEAM),是 IBM 开发的一个静态分析工具,可以用于分析并查找出 C, C++ 和 Java代码中的一些不容易发现的潜在错误,从而达到提高代码质量的目的。同动态分析工具和其它静态分析工具相比,它拥有一些可贵的特性。
特点

1、对代码进行语法扫描,通过算法对代码进行检查分析
2、和一些 bug 模式进行比较,最终标明问题区域,输出分析结果
3、使用了额外的定理证明(theorem proving)技术来判断一个潜在的错误是否是真正的错误,从而减轻了程序员判断错误真伪所需的工作量

3.19 LDRA Testbed 

        LDRA Testbed为应用软件的确认和验证提供强大的源代码测试和分析功能,是独特的质量控制工具。 它有助于提高计算机软件必需的可靠性,健壮性和尽可能的零缺陷,它的使用带来时间、成本和效率上真实的节省,这些都是无法衡量其价值的。它是强大和完整的集成工具包,使先进的软件分析技术应用在开发生命周期的关键阶段。

        LDRA Testbed提供强大的分析功能,用于两个主要的测试领域,静态分析和动态分析。

1)静态分析: 分析代码,并且提供对代码结构的理解。
2)动态分析: 利用源代码的插装版本,使用测试数据执行,在运行时发现软件缺陷

        使用LDRA testbed 的好处:

1、软件开发和测试过程的成本效率分析工具

2、单元、集成和系统测试的理想工具 

3、贯穿于软件开发的整个生命周期

        LDRA Testbed应用于许多不同的领域 

过程改进

软件测试

软件维护

        LDRA Testbed的优点:

1、改进软件质量
2、定位软件缺陷
3、强制执行工业标准
4、减少维护费用40%以上
5、减少开发和测试成本75%以上
6、通过自动化过程提高员工动力

3.20 Yasca 

        Yasca是一个开源静态代码分析工具插件框架, 集成流行的多语言静态分析工具,如findbugs/pmd/jlint/rats/cppcheck,由于插件本身多样故可支持java、c++等语言静态分析.Yasca是一个用来寻找安全漏洞,在程序的源代码中检测代码质量、性能以及一致性的软件。它集成了其他开源项目,其中包括FindBugs,PMD ,JLint , Cppcheck ,并扫描某些文件类型,以及自定义扫描书面的。

3.21 阿里系列的代码监测工具

  • 代码质量检测

(1)Java代码规约检测

        提供 IDEA 插件 Alibaba java coding guideline,方便集成在IDEA,实时发现并修改不规范代码。有一份详细的 pdf 文档《码出高效:阿里巴巴 Java 开发手册》解释编码规范;作为阿里内部 Java 工程师所遵循的开发规范,涵盖编程规约、单元测试规约、异常日志规约、MySQL 规约、工程规约、安全规约等。这是近万名阿里 Java 技术精英的经验总结,并经历了多次大规模一线实战检验及完善。比较好的是:针对插件检查出来的不规范,有详细的解释。

         代码规约通过 IDE 检测插件、流水线集成测试、代码评审集成等工具手段,深度融入了阿里巴巴的各种开发活动中。与此同时,在云效代码托管平台 Codeup 中,也内置集成了 Java 代码规约检测能力,为开发人员在代码提交和代码评审阶段提供更为方便的快速检查。目前开发者可从云效官网访问并免费使用。“云效代码管理”(Codeup)是一款企业级代码管理平台,提供代码托管、代码评审、代码扫描、质量检测等功能,保护企业代码资产,实现安全、稳定、高效的研发生产。云效代码管理(Codeup)主要提供代码浏览、代码评审、配置管理(SCM)、代码扫描、代码安全、CI/CD、文档、代码库迁移等能力和服务。在代码质量方面,内置了阿里自研的P3C代码规划检测插件。

        详细介绍: http://www.hzhcontrols.com/new-1407578.html

(2)代码智能补丁推荐

        缺陷检测和补丁推荐几十年来一直是软件工程领域的难题,又是研究者和一线开发者最为关心的问题之一,这里讲的缺陷不是网络漏洞、系统缺陷,而是隐藏在代码中的缺陷。帮助开发者识别这些缺陷,并进行修复,能够大幅提升软件质量。

        基于业界和学术界较为流行的缺陷检测手段,并分析和规避其局限性,阿里巴巴 Codeup 的算法工程师们提出了一种新的算法,实现更加精准和高效的分析代码缺陷并推荐优化方案,该算法已被国际软件工程大会(ICSE)收录。

1、根据 commit message 中的关键词找出修复型的 commit,只取涉及文件小于 5 个的 commit(涉及文件过多的 commit 可能会稀释修复行为)。这个步骤十分依赖开发者良好的 commit习惯,希望开发者能用好 commit,写好 message。

2、从这些修复型 commit 中以文件级别提取删除内容和新增内容,即 Defect and Patch pairs(DP Pair),这一步难免会有很大的噪声。

3、利用改进的 DBSCAN 方法对 buggy 和 patch 对同时聚类,将相似的缺陷和补丁代码聚在一起。(也可以做片段级的聚类)通过将相似的缺陷和修复做聚类,减少了上一步留下的大量噪声,同时历史代码提交中大家共同犯过的错具有很强的借鉴意义。

4、利用自研的模板提取方法总结缺陷代码和补丁代码,并根据不同的变量来适配上下文。

        代码补丁推荐服务目前应用于合并请求的代码自动扫描场景,在代码评审过程中检测可优化代码片段并给出优化建议,将历史评审中的人工经验沉淀下来持续提升企业代码质量。

  •  代码安全检测

(1)敏感信息检测

        近年来,业内发生多起敏感信息(API Key、Database credential、OAuth token 等)通过某些站点被无意识地泄露出去的事件,给企业带来了安全风险,甚至直接的经济损失。

        在很多实践过程中,面临了类似的问题,硬编码问题出现非常高频,而又缺乏有效的识别机制。因此开发者和企业管理者亟需一款稳定健全的敏感信息检测方法和系统。通过调研阿里了解到,目前已有的敏感信息检测工具大多单纯使用规则匹配或信息熵技术,导致其召回率或准确率难以满足预期。因此阿里在规则匹配和信息熵技术的基础上,结合上下文语义,提出了一款采用多层检测模型的敏感信息检测工具——SecretRadar。

        SecretRadar 的技术实现思路主要分为三层,第一层采用规则匹配这种传统敏感信息识别技术,规则匹配具有良好的准确度和扩展性,但是非常依赖比较固化的长度、前缀、变量名,难以应对不同开发者的不同编码风格,容易造成漏报。针对难以固定规则捕捉的场景,在第二层采用了信息熵算法。信息熵算法用于衡量代码行混乱程度,对随机生成型密钥和随机身份信息识别效果良好。但信息熵算法也有其局限性,召回率提升的同时误报也增多了。因此在第三层采用了模板聚类和上下文语义分析等方法进行过滤优化,针对信息熵结果聚合提取常见关键字,结合上下文语义和当前语法结构提升模型准确率。

        敏感信息检测工具不止服务阿里内部开发同学,在云效平台上也支持了超过 2 万代码库、3 千家企业,帮助开发者解决了超过 9 万硬编码问题。

(2)源码漏洞检测

        阿里巴巴采用 Sourcebrella Pinpoint 源伞检测引擎,进行源码漏洞检测,主要涉及到注入类风险和安全策略类风险检测。

        源伞检测引擎是香港科技大学 Prism 研究组在过去十年的时间内的技术研究成果。该引擎吸收了国际上近十年的软件验证技术研究成果,并且加以改进和创新,独立设计和实现了一套技术领先的软件验证系统。其主要验证方式是将编程语言翻译成一阶逻辑和线性代数等数学表达,通过形式化验证技术推理缺陷成因。迄今为止,一共发表了四篇核心技术相关的论文,一篇 PLDI 和三篇 ICSE,研究型的同学可以点击文末链接阅读。

        源伞检测引擎能够在活跃度比较高的大型开源项目中发现隐藏超过 10 年的缺陷,以 MySQL 检测 [5] 为例,这些缺陷都是市面上其他检查工具无法扫描出来的,并且能够在 1.5 小时完成 200 万行大型开源项目的检测。在保持扫描的高效率同时,还能够将误报率控制在 15%左右。对于复杂且体量庞大的分析项目来说,源伞检测引擎所表现的扫描效率和误报率在业内也处于领先水平。

        「源码漏洞检测」集成了源伞检测引擎的安全分析能力,能够在分析精度、速度、深度等方面均衡得到较好的分析结果,具备的核心优势:

1、支持分析字节码,二三方包的代码逻辑都不会遗漏;

2、擅长跨函数长调用链路的逻辑分析;

3、可以处理引用、指针等带来的间接数据修改;

4、精度高,相比于同类工具,如 Clang、Infer,在精度和有效问题识别上表现更佳;

5、性能好,目前单应用平均 5 分钟左右分析完毕;

        源伞检测引擎可以精确的追踪代码中的数据流向,拥有高深度高精度的函数调用链分析能力,可以找到跨越多层函数的深度问题。在发现缺陷的同时还能给出问题触发的过程,完整展示相关的控制流以及数据流,这样可以辅助开发者快速理解和修复问题,在软件开发早期更低成本地提高软件质量,大幅减少生产成本,提高研发效能。

(3)依赖包漏洞检测

        阿里期望对于开源组件的安全可信程度,为开发者建立一种有效的检测和管理机制,因此实现了依赖包漏洞检测服务和依赖包安全问题报表。在实践过程中,开发者普遍反映依赖包漏洞修复成本大多高于修复自身编码漏洞,从而不愿意或难于处理此类问题。究其原因,一方面是大部分漏洞并非直接引入,而是依赖的第三方组件又间接依赖了其它组件,另一方面是不确定具体哪个版本是干净可用且兼容的。

        为了降低开发者的修复难度,阿里对依赖项的引用关系进行了进一步识别分析,清晰的标注出直接依赖和间接依赖,并定位到具体的依赖包引入文件,方便开发者快速找到关键问题位置。同时,通过对漏洞数据的聚合,智能推荐修复漏洞的版本升级建议,因为一个依赖可能对应多个漏洞问题,开发者可以针对建议评估是否接受采用。通过分析不同版本间的 API 变更和代码调用链路,衡量版本升级成本,为开发人员自动创建修复评审,最大程度的帮助开发人员更高效地维护代码安全。

        无论是代码质量检测还是代码安全检测,以上 5 款阿里代码自动检测工具,开发者们都可以在云效 Codeup 内免费体验。

四、实施

        上面讲了不少工具,可是规范毕竟是规范,不实施起来,强硬提交(--force或者--hard)也是无奈。所以有必要设置一个关卡,不满足则不让提交或者失败;可以从两个地方加以控制实施。

4.1 VCS 服务端

        在 version control system 服务端(如git,svn服务端)实施,如果不达标则拒绝提交(允许提交到其他分支以便保留工作成果,但是不能 merge 到 master 或者 release branch)。提交代码前自动执行检查,想到Git commit hook,比如 pre-commit hook

#!/bin/sh
# From gist at https://gist.github.com/chadmaughan/5889802
# stash any unstaged changes
git stash -q --keep-index
# run the tests with the gradle wrapper
./gradlew clean build
# store the last exit code in a variable
RESULT=$?
# unstash the unstashed changes
git stash pop -q
# return the './gradlew build' exit code
exit $RESULT

        将该脚本拷贝到项目.git/hooks/下,在执行git commit时自动触发检查,检查失败则提交失败。.git隐藏文件夹并不能提交到远程代码仓库,除非人工分发和拷贝外,有没有更好的方式在团队中共享这个机制呢?

        可以把pre-commit纳入版本控制(如config/pre-commit),再使用构建工具的扩展机制来自动完成拷贝工作,这样可以间接实现git hooks的团队间共享。缺点:没有使用 gradle,使用 maven 怎么做?

# build.gradle
task installGitHooks(type: Copy) {
    // 将pre-commit拷贝到指定位置
    from new File(rootProject.rootDir, 'config/pre-commit')
    into {
        new File(rootProject.rootDir, '.git/hooks')
    }
    fileMode 0755
}
// 设置执行build任务时会自动触发installGitHooks任务
build.dependsOn installGitHooks

4.2 CI/CD 服务端

        利用 CI/CD 服务端,在 Jenkins 构建(Jenkins 集成 checkstyle 或者 sonarqube)或者随后的部署阶段检查代码质量,不满足则触发失败。或者如果使用 maven-checkstyle-plugin,则可以随时触发检查。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐