代码规范问题

最近有做简单的代码规范整理,写一下规范过程使用的工具和遇见比较多的问题。

 

一、代码规范的重要性

  关于代码规范的重要性网上一搜一大堆,都是很有年代的一些文章,现在写这个好像有点太low了,简单列一下他们(相似的文章太多,找不到原文)所说到的几点好处:

  • 有助于团队合作
  • 减少BUG处理
  • 降低维护成本
  • 有助于代码审查
  • 养成规范代码的习惯,有助于程序员自身的成长

  毋庸置疑的是随着团队的发展、规范化,良好的代码规范能体现的好处会越来越明显,提升工作效率、提高代码质量等等...

 

二、如何保证代码规范

   为了保证代码的规范、质量,需要开发者自身养成良好的编码习惯,但是很多时候每个人的风格习惯都不一样,不利于团队协作,即使有些公司会有人工代码审查的环节,但是过于耗费人力资源,所以更多的是利用工具进行扫描分析。

代码分析包括静态分析和动态调试:

  • 静态分析:指在不运行程序的情况下,对源代码进行检查分析,通过分析语法、结构、过程、接口等来检查程序的正确性,找出代码中存在的错误和缺陷。如参数不匹配、有歧义的嵌套语句、错误的递归、非法计算、可能出现的空指针引用等等。
  • 动态调试:指利用调试器跟踪软件的运行,寻找程序中的漏洞。

  现在主要是利用以静态分析技术实现的相关工具对代码进行检查,先列一下接触到的工具:

 工具  分析对象  备注
 Findbugs 字节码文件  缺陷模式匹配、数据流分析。通过字节码分析代码存在缺陷、支持数据流分析,能查找出空指针崩溃等问题。
 CheckStyle Java源代码  缺陷模式匹配。扫描代码格式规范、代码风格的工具。
 Alibaba java coding guidelines(基于PMD) Java源代码  缺陷模式匹配、数据流分析。检测代码潜在错误。

 

 

三、工具以及事例
  • FindBugs

    FindBugs是一个开源的静态代码分析工具,基于LGPL开源协议,它检查类或者JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。它注重检测真正的bug及潜在的性能问题 ,尤其注意了尽可能抑制误检测(false positives)的发生,不关心代码风格格式的问题。FindBugs的检测结果主要分一下几种问题类型:

    • 正确性(Correctness):可能导致错误的代码。比如错误的强制类型转换。
    • 最佳实践反例(Bad practice):违反了公认的最佳实践标准。如一些流使用后没有关闭。
    • 多线程的正确性(Multithreaded correctness):关注于同步和多线程问题。如应该使用notify()而不是notifyAll()。
    • 性能(Performance):潜在的性能问题。如:一个属性从没有被使用,考虑从类中去掉。
    • 危险的(Dodgy):具有潜在危险的代码,可能运行期产生错误。如:对方法调用的直接引用,而方法可能返回null。
    • 恶意代码漏洞(Malicious code vulnerability):可能受到恶意攻击的代码,如访问权限修饰符的定义等。
    • 国际化(Internationalization):关于代码国际化相关方面的。如使用平台默认的编码格式对字符串进行大小写转换,这可能导致国际字符的转换不当。

    

    简单列几个我们程序中FindBugs分析出现比较多的问题:

  1. May expose internal representation by returning reference to mutable object.

    可能因使引用可指向多个对象而暴露内部存储结构。

    get/set方法直接把此对象中某一属性的引用放到外部,可以随便更改,违反了封装的原则。可以在get/set方法中修改为对这类属性(引用地址)的拷贝对象做操作。但是一般不会这么做,实际使用中bean里面的属性设置后很少会再改动,这么做太麻烦了。

  2. Method invokes inefficient Number constructor; use static valueOf instead.

    方法调用低效数构造函数,使用静态valueOf方法代替。

    FindBugs推荐使用Integer.ValueOf(int)代替new Integer(int),因为这样可以提高性能。如果当你的int值介于-128~127时,Integer.ValueOf(int)的效率比Integer(int)快大约3.5倍。从源代码可以看到,ValueOf对-128~127这256个值做了缓存(IntegerCache),如果int值的范围是:-128~127,在ValueOf(int)时,他会直接返回IntegerCache的缓存。

  3. Boxed value is unboxed and then immediately reboxed.
    装箱的值被拆箱,然后立即重新装箱了。

     自动装箱拆箱的特性,只要运算中有不同类型,当涉及到类型转换时,编译器就会向下转型,再运算。

  4. Switch statement found where default case is missing.
    Switch没有默认情况下执行的case语句。

     

  5. Inefficient use of keySet iterator instead of entrySet iterator.
    使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。

    当程序中有遍历对map的key、value操作的时候,建议使用entrySet,它的性能比keySet高。通过keySet遍历时,生成KeyIterator迭代器,如果要获取value此时还要遍历Map。而entrySet遍历生成EntryIterator 迭代器,其中包含key和value。

  6. Method call passes null for non-null parameter.
    对参数为null的情况没做处理。

     当args为空时,程序异常。

  • Checkstyle

    Checkstyle是一款检查Java程序源代码样式的工具。主要的检查项包括Javadoc注释、命名规范、多余没用的Imports、Size度量,如过长的方法、缺少必要的空格Whitespace、重复代码等。它可以有效的帮助我们检视代码以便更好的遵循代码编写标准,特别适用于小组开发时彼此间的样式规范和统一。

    按照Sun的规范太严格了,通常需要自定义规则,使用起来很麻烦,所以后面没有使用Checkstyle。

  • Alibaba java coding guidelines

    Alibaba java coding guidelines是阿里巴巴2017年10月在杭州云栖大会上发布的,把《阿里巴巴 Java 开发规约》强制条目转化为自动插件,并实现了部分的自动编码。项目已经在Git上开源了,地址阿里规约插件

    阿里规约插件检查的内容参照《阿里巴巴 Java 开发规约》,基于PMD进行的代码检测,检测的问题主要分为三类,对应 Snoar 中的前三个等级,前两个级别是必须要处理的:

    • Blocker:崩溃
    • Critical:严重
    • Major:重要

    

 

    按照阿里规约,大量存在的问题如下,因为是中文的,而且提示信息很准确,所以修改很轻松:

    • 方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式。
    • 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
    • 魔法值。
    • 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
    • 注释的双斜线与注释内容之间有且仅有一个空格。
    • Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
    • 集合初始化时,指定集合初始值大小。
    • 需要进行参数校验。
    • 类、类属性、类方法的注释必须使用 Javadoc 规范,使用/**内容*/格式。

 

四、总结

   其实单从这里并不能很好的做到代码规范统一,了解到正常的应该是类似Jenkins+SonarQube+Git的方式,在提交代码的时候会触发检查,不合规范的代码不允许提交。

posted @ 2018-12-17 17:34  小劉同学  阅读(1938)  评论(0编辑  收藏  举报