本文主要是介绍百度高效研发实战训练营-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中有两种数组定义形式,为规范代码书写形式,要求为:
- 类型与中括号紧挨相连来表示数组,即中括号写在数组名之前
而当注解与注释同时存在时,统一的规范要求为:
- 添加在类、方法、构造函数、成员属性上的注解,直接写在注释块之后,每个注解独占一行
当同时存在多个修饰符时,需要按照顺序书写,顺序要求如下:
为避免小写字母,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的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!