百度高效研发实战训练营-Step4

2022/6/13 23:22:08

本文主要是介绍百度高效研发实战训练营-Step4,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

百度高效研发实战训练营-Step4


4.1 代码检测规则:Java案例详解

以Java的案例进行代码检查规则解释,代码检测规则可以分为以下十类:

4.1.1 源文件规范

该类规范,主要为从文件名、文件编码、特殊字符等三个方面制定的规则。

  • 文件名方面:Java源文件名,必须和它包含的顶层类名保持一致,包括大小写,并以.java作为后缀名。

  • 文件编码方面:为了保持编码风格的一致性,避免编码不一致导致的乱码问题,要求所有源文件编码必须使用UTF-8格式。

  • 特殊字符方面:针对换行、缩进、空格等操作而制定,有以下强制规则:

    • 1 换行符以外,ASCII空格(0x20)是唯一合法的空格字符。

    • 2 由于不同系统将Tab转换成空格的数目不一致,统一使用空格进行缩进。

    • 3 文件的换行符统一使用Unix格式(\n),而不要使用Windows格式(\r\n)

4.1.2 源文件组织结构规范

这一大类规则规定了源文件所应包含的具体组成部分,和各个部分间应遵循的一系列规则。
对于源文件的组成部分,规定如下:
源文件,必须按照顺序包含以下内容,许可证或版权声明、package、import、唯一的顶层类四个方面的内容。同时,每两个部分之间用一个空行进行分隔,不允许出现多余空行,对于以上四个方面的内容,每个组成部分又有相应的编码规则。

1 许可证或版权声明

  • 如果文件有许可证或版权声明,应放在最开头,如果没有,则可以忽略这部分。

2 package语句

  • package语句一定单独占一行不换行
  • 允许超过Java的120字符列宽限制

3 import语句

  • 对于所有非静态导入,禁止使用通配符import
  • 所有未使用的import语句均应删除,并且与package语句相同
  • 每条import语句单独占据一行不换行,允许超出120字符列宽限制

4 唯一的顶层类

类声明规范

  • 每个源文件只允许包含唯一一个顶层类,若需要定义其他的类,可将多余的类放在另外一个独立的源文件中,或者可将其作为一个内部类,定义在顶层类中来使用
  • 重载的方法必须放在一起,即同名的构造函数或方法之间禁止插入其他成员

4.1.3 代码结构规范

这一部分规则,主要是对花括号(即大括号),缩进与换行、空行的一系列规范和其他说明。

1 花括号

花括号,经常在类和方法定义以及代码块划分中使用,花括号在使用中常需要合理的换行操作进行配合,规定为:

  • 在非空代码块中使用花括号时,要遵循K&R风格(Kernighan and Ritchie Style)。

三个主要原则为:

  • ①在左花括号({})前不能换行,在其后换行
  • ②在右花括号(})前应有尽有
  • ③表示终止的右花括号(})后必须换行,否则,右花括号后不换行。

2 缩进与换行

缩进与换行,主要是为了保证代码风格的一致性,提升代码的可维护性。
主要规范有:

  • ①每次开始书写一个新代码块时,使用四个空格进行缩进,在代码块结束时,恢复之前的缩进级别。

  • ②每条语句之后都要换行,每行只能有一条完整语句

  • ③除package语句import语句外,单行代码字符数限制不超过120个。
    超出则需要换行,换行时,遵循如下五条原则:

    (1) 第二行相对于第一行缩进四个空格,从第三行开始,不再继续缩进。
    (2) 运算符与下文一起换行,即运算符位于行首

    (3) 方法调用的点符号与下文一起换行

    (4) 方法调用中的多个参数需要换行时,在逗号后进行
    (5) 在括号前不要换行

3 空行

合理使用空行,可以提高代码的可读性,有利于后期维护。
对于空行的使用,有如下规范进行约束:

  • ①在类的不同成员间增加空行,包括:成员函数、构造函数、方法、内部类、静态初始化块、实例初始化块等。
  • ②在两个成员变量声明之间可以不加空行。空行通常用于成员变量进行逻辑分组。
  • ③方法体内,按需增加空行,以便从逻辑上对语句进行分组。
  • ④使用空行时,禁止使用连续的空行。

4 其他说明

Java中有两种数组定义形式,为规范代码书写形式,要求为:

  • 类型与中括号紧挨相连来表示数组,即中括号写在数组名之前

而当注解与注释同时存在时,统一的规范要求为:

  • 添加在类、方法、构造函数、成员属性上的注解,直接写在注释块之后,每个注解独占一行

当同时存在多个修饰符时,需要按照顺序书写,顺序要求如下:

  • 排在首位的一定是访问修饰符,随后是abstract,即抽象类或抽象方法,紧接着是staticfinal。这是常见的几类修饰符,对于其他的修饰符,可以参考以上列举的顺序书写。

    public protected private abstract static final 
    transient volatile synchronized native strictfp
    

为避免小写字母,l与1混淆,有如下规定:

  • 常整型数字必须使用大写字母L结尾,以便于和数字1进行区分

4.1.4 命名规范

在Java中,无论是方法名还是类名,均需使用驼峰命名格式进行命名。

1 驼峰命名格式

对于两种驼峰命名格式的使用范围,有如下规范:

  • ①方法名、参数名、成员变量、局部变量都统一使用lowerCaeCase风格,即首字母小写的驼峰命名格式
  • ②类名使用UpperCamelCame风格,即首字母大写的驼峰命名格式,以下情形例外:DO/BO/DTO/VO/AO/PO/UID等。

2 类的命名格式

除此之外,对于一些类,命名格式有更加具体的规范要求:

  • ①抽象类命名,使用Abstact或Base开头
  • ②异常类命名使用Exception结尾
  • ③测试类命名以它要测试的类的名称开始,以Test结尾。

3 常量命名格式

对于常量的命名规范,与上述所述有所不同:

  • ①常量命名全部大写,单词间用下划线隔开;
  • ②不允许任何未经定义的常量直接出现在代码中。

4.1.5 OOP规约

OOP规约,主要是针对面向对象编程过程中,定义的一些类所制定的一些规则,包含的强制规范要求有

  • ①所有POJO类属性,必须使用包装数据类型,禁止使用基本类型。
  • ②所有的覆写方法,必须加@Override注解
  • ③Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals
  • ④定义DO/DTO/VO等POJO类时,均不要设定任何属性默认值。

4.1.6 集合处理规范

集合和数组,是我们开发过程中使用频度最高的两个数据结构。
对于二者的使用,也有严格的强制规范:

  • ①当需要将集合转换为数组时,必须使用集合的toArray方法,传入的是类型完全一样的数组,大小是list.size()。
  • ②对一个集合求子集合时,需高度注意对原集合元素的增加或删除,均会导致子列表的遍历、增加、删除,产生ConcurrentModificationException异常。应通过对子集合进行相应操作,来反射到原集合,从而避免异常的发生。
  • ③不要在循环体内部进行集合元素remove/add操作。remove元素请使用Iterator(迭代器)方式,如果并发操作,需要对Iterator对象加锁。

4.1.7 控制语句规范

Java中的控制语句主要有Switch、if、else、while。这些语句的使用在编码过程中需要遵循以下规范:

  • (1)在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个stitch块内,都必须包含一个default语句并且放在最后。
  • (2)使用if/else/while/do语句必须使用花括号。即使只有一行代码,避免采用单行的编码方式。
  • (3)在高并发场景中,避免使用“等于”判断作为中断或退出的条件。防止在击穿现象下,程序无法正常中断或退出的情况发生。

4.1.8 注释规约

合理使用注释可以提高程序可读性,从而便于后期的维护。
注释可以是程序说明,也可以是编程思路。
Java中的注释主要分三种形式:文档注释、单行注释和多行注释
注释规约包括:

  • ①类、类属性、类方法的注释必须使用文档注释形式,即使用\(/**内容**/\)格式,不得使用单行注释的格式。单行注释和多行注释主要使用在方法体内。
  • ②方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释,使用\(/*内部*/\),注释与代码对齐。

4.1.9 异常处理规范

在Java中,我们通常使用try catch来进行捕获异常处理,而Java中的异常又分为运行时异常和非运行时异常。对于处理运行时异常,有如下规范:

  • ①Java类库中定义的可以通过预检查方式规避的RuntimeException异常不应该通过try catch的方式来处理,比如:空指针异常和数组越界异常等等。
  • ②对于捕获后异常的处理,有如下规范:捕获异常是为了处理异常,不要捕获后不进行任何处理而将其抛弃。
    若不想进行异常的处理,则应将该异常抛给它的调用者。
    最外层的业务使用者必须处理异常,将其转化为用户可以理解的内容。
    即对于捕获后的异常,要么继续向上抛,要么自己进行处理。
  • ③异常处理的规范要求还包括:不能在finally块中使用return语句。

4.1.10 缺陷检测规则

缺陷检测要是对Java源代码进行静态分析,扫描其中潜在的缺陷,比如空指针异常、死循环等。

这一阶段所应遵循的规则包括:

  • (1) 不能使用单个字符定义StringBuffer和StringBuilder;
  • (2) 任何上锁的对象均需保证其锁可以被释放
  • (3) 严格避免死循环的发生
  • (4) 对于字符串中的点号(".")、竖线("|")和文件分隔符("File.separator")进行替代时,需要注意其特殊含义。
    “.”:匹配任意单个字符。在replaceAll中使用,它匹配所有内容。
    “|”:通常用作选项分隔符,它匹配字符间的空格。
    “File.separator”:匹配特定平台的文件路径分隔符。在Windows上,这将被视为转义字符。
  • (5) 当synchronize对成员变量进行上锁时,该成员变量必须是final类型的。
  • (6) synchronize上锁的成员变量类型一定不能是装箱类型。
  • (7) 所有被spring托管的类,其成员属性的初始化均要使用注入的方式。
  • (8) 当使用try catch方式进行异常捕获,且需要在catch中对异常信息进行输出时,不得使用printStackTrace的方式。
    这种方式会导致后期分析代码困难。而应采用一些Log框架,方便用户检索和浏览日志。
  • (9) 方式返回值包含操作状态代码时,该状态码不应被忽略
  • (10) 【%s】数组具有协变性,元素赋值类型与初始化类型不一致,此种情况可通过编译,但运行阶段会发生错误。
  • (11) 对于用户名和密码不应直接写在Java的文件中,避免泄露。而应将相信关键信息写在配置文件中进行读取。
  • (12) 方法和成员变量的命名不应相同,也不应通过大小写进行区分。

4.2 单元测试之Java实践

如何写单元测试,这部分包括四个方面,基本流程、测试替身、设计思路、断言(Assertions)。

4.2.1 如何写单元测试

1 基本流程

单元测试的基本流程如下,首先,环境初始化,其次准备输入参数,再次,调用待测试方法,然后检查输出,最后测试完成后环境复原。

环境初始化=>准备输入参数=>调用待测试方法=>检查输出=>测试完成后环境复原。

2 测试替身

下面来介绍一下什么是测试替身。
测试替身,可用于隔离被测试的代码,加速执行顺序,使得随机行为变得确定,模拟特殊情况,以及能够使测试访问隐藏信息等。
在Java代码开发过程中,替身测试能够保证单元测试的独立性与重复性。
常见的测试替身有四类:桩(Stub)、伪造对象(Fake)、测试间谍(Spy)、模拟对象(Mock)等。

对于以上四个类别:

1 桩(Stub)

对于桩,一般什么都不做,实现空的方法调用或者简单的硬编码返回即可。

2 伪造对象(Fake)

真实数据的简单版本,伪造真实对象的欣慰,但是没有副作用或者使用真实事物的其他后果。比如替换数据库的对象,而得到虚假的伪造对象。

3 测试间谍(Spy)

需要得到封闭对象内部状态的时候,就要用到测试间谍,事先学会反馈信息,然后潜入对象内部去获取对象的状态。测试间谍是一种测试替身,它用于记录过去发生的情况,这样测试在事后就能知道所发生的一切。

4 模拟对象(Mock)

模拟对象是一个特殊的测试间谍。是一个在特定的情况下可以配置行为的对象,规定了在什么情况下,返回什么样的值的一种测试替身。目前Mock已经有了非常成熟的对象库,包括JMock、Mockito和EasyMock等。

下面重点讲一下,模拟对象(Mock)。

假如我们有业务逻辑,数据存取,数据这三层逻辑。
现在需要对业务逻辑层进行单元测试,那么我们可以使用Mock,对数据存取和数据层的内容进行模拟,从而使上面的单元测试是独立的。

3 设计思路

下面来讲解怎样通过测试替身来写单元测试:
单元测试case的核心与当前函数的功能实现,对于输出数据做出具体的预期,即可把全部待测试的分支都罗列出来。
应用场景+输入数据+功能实现=输出数据。

4 断言(Assertions)

断言,是一种在Java单元测试中经常使用的测试方法,在单元测试中,我们使用断言,来检验当前的测试结果是成功还是失败。

常见的断言有:Assert.assertNotNull、Assert.assertEquals、Assert.assertTrue、Assert.assertFalse、Assert.fail。无需人工对单元测试结果进行判断。

4.2.2 单元测试的运行

单元测试的运行:
单元测试的运行分为手动与自动两种,第一种是手动方式:

  • 直接在IDE中执行
    在开发编码完成之后,开发人员可以直接在自己的环境和编译器内运行单元测试。
  • 使用Maven的mvn test
    Maven是目前Java开发中最流行的项目构建工具,它包含了很多功能,非常全面。mvn test这个测试模型就可以为我们的单元测试提供极大的便利。

第二种方式是自动运行:

  • 持续集成(Jenkins)
    自动化持续集成是我们在项目中常用的一种单元测试的方法。通用工具为Jenkins,Jenkins是一种持续集成的工具,它的功能非常强大。他的主要的功能有软件发布和版本测试、外部调用测试。

4.2.3 如何判断单元测试的质量

首先来看一下,单元测试的衡量标准。
从主观层面,优秀的单元测试可读性高、易于维护、值得信赖。
从客观层面,使用单元测试代码覆盖率来衡量,覆盖率工具包括:集成IDE和单独部署。

4.3 如何做好Code Review



这篇关于百度高效研发实战训练营-Step4的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程