代码走查具体考察点
一、参数检验
- 公共方法都要做参数的校验,参数校验不通过,需要明确抛出异常或对应响应码。
- 在接口中也明确使用验证注解修饰参数和返回值,作为一种协议要求调用方按注解约束传参,返回值验证注解约束提供方按注解要求返回结果。
二、魔法数字(幻数)
在代码中要杜绝幻数,幻数可定义为枚举或常量以增强其可读性。
三、空指针检验
- 不确定返回集合是否可为空时,要先做非空判断,再做for循环。
- 尽量返回空对象,或者空集合,而不是null。
- 判断字符串为空时,先判断是否为空,再判断是否空串,最好将其提出公共方法。
- 使用a.equal(b)时,把常量放在左边。
四、下标越界
如果方法传入数组下标作为参数,要在一开始就做下标越界的校验,避免下标越界异常。
五、重复代码检验
不允许写重复代码(四行左右重复计算重复代码),重复代码要使用重构工具提取重构。
六、命名规范
- 包、类、方法、字段、变量、常量的命名要遵循规范。
- 命令要名副其实,一方面增加可读性,另一方面促使我们在起名的过程中思考方法、变量、类的职责是否合适。
- 尽量不要在循环中调用服务,不要在循环中做数据库等跨网络操作。
- 循环或者递归,要注意其是否一定包含了停止循环/递归的条件。
- 尽量避免while(true),一定要写的话,循环开始要加一个sleep,这样避免一上来就异常,跑死CPU。
七、注意循环
八、关心频率
写每一个方法时都要关心这个方法的调用频率,一天多少,一分多少,一秒多少,峰值可能达到多少,调用频率高的一定要考虑性能指标,考虑是否会打垮数据库、缓存等。
九、差错控制
- 避免过大的 try 块,不要把不会出现异常的代码放到 try 块里面,尽量保持一个 try 块对应一个或多个异常。
- 细化异常的类型,不要不管什么类型的异常都写成 Excetpion。
- catch 块尽量保持一个块捕获一类异常,不要忽略捕获的异常,捕获到后要么处理,要么重新抛出新类型的异常。
- 方法内部,不要把自己能处理的异常抛给别人。
- 不要用 try...catch 参与控制程序流程,异常控制的根本目的是处理程序的非正常情况。
十、关于长度
如果一行代码过长,要分解开来;如果一个方法过长,要重构方法;如果一个类过长要考虑拆分类
十一、外部依赖的性能
如果调用了外部依赖,要搞清楚这个外部依赖可以提供的性能指标,考量其是否能够提供符合我们使用场景的服务。
十二、避免重复造*
不要重复造*,如果已经有成熟类库实现了类似功能,要优先使用成熟类库的方法,这是因为成熟类库中的方法都经过很多人的测试验证,已经非常可靠了。
十三、注意多线程
多线程环境中,要注意数据的原子性与可见性等线程安全问题,最典型的HashMap,SimpleDateFormat,ArrayList是非线程安全的,另外如果使用Spring自动扫描服务,那么这个服务默认是单例,其内部成员是多个线程共享的,如果直接用成员变量是有线程不安全的。
十四、日志打印
- 打印日志要设定合理的日志级别。
- 生成长字符串的toString()时,通过日志级别和if语句达到控制打印量的目的。原因是,长字符传拼接会占用很多gc年轻代内存。
- 要通过log4j打印日志而不是直接把日志打印到控制台。
十五、方法实现的简洁
这个无法说的太细,总之是不要啰里啰嗦的写代码,具体问题要具体分析。
十六、正向依赖
不能让底层模块依赖于上层模块;不能让数据层依赖于服务层;也不能让服务层依赖于UI层;更不能在模块之间形成循环依赖关系。
十七、分治
分而治之,复杂的问题要分解成几个相对简单的问题来解决,首先要分析出核心问题,然后分析出核心的入参是什么,结果是什么,入参通过几步变化可以得出结果。(该条与第十条:关于长度,有一定的重合)
十八、代码健壮性意识
该条是前面几条的整合,比较综合。考虑各种边界条件(例如第四条下标越界、用户输入数据超出最大值等)、处理失败或出异常的方法(参考第九条、差错控制)、校验入参和返回值(参考第一条参数校验)