摘要:通过工具对Android项目源码进行质量检测

从开发的角度来讲,一款软件的优秀与否,除了与软件整体架构有关,还决定于开发者的编码是否规范以及能否对相关平台特性的充分利用。对于软件的整体架构,目前阶段我们只能依靠开发者的经验,去构建良好的架构。对于编码是否规范以及平台特性的使用,除了开发者的编码经验,我们还可以依赖一些工具来对我们编写的源码进行检查,来提高代码的质量。本文将以Android为平台,对三种代码质量检查的工具进行介绍。

一、Android SDK中自带的StrictMode(限制模式)

最新的Android平台中(Android 2.3起),新增加了一个类,叫StrictMode(android.os.StrictMode),这个类可以用来帮助开发者改进他们编写的应用,并且提供了多种策略,这些策略能及时的检查应用中存在的问题。

我们可以在项目的开发测试阶段,将项目ProjectBuild Target改为Android2.3或2.3以上,使用系统提供的StrictMode(限制模式)来进行开发测试,并使用 StrictMode给我们提供的多种限制策略,进行单个线程,或者整个jvm的监测,例如,我们通过使用ThreadStrictMode对磁盘读写和网络进行检测,当程序运行过相关的代码后,我们就可以得到所有读写磁盘和访问网络所消耗的时间,进而是我们得知项目当中哪些地方耗时过长,我们就可以在那些不合理的地方进行优化。


StrictMode还给我们提供了多种形式的策略违背输出,例如log日志,运行时弹出对话框等模式。StrictMode的使用也是非常简单。例如,你想对UI线程中的读磁盘进行检测,你只需要在主线程当中Activity的onCreate方法加入以下代码即可:

StrictMode.setThreadPolicy((newStrictMode.ThreadPolicy.Builder()).detectDiskReads().penaltyLog().penaltyDialog().build());


当有读取磁盘的时候便会在log中输出以下内容(并且会在正在运行的模拟器或手机上弹出对话框,提示当前程序有策略违背):

10:03:56.122:DEBUG/StrictMode(16210):StrictModepolicyviolation;~duration=696ms:android.os.StrictMode$StrictModeDiskReadViolation:policy=23violation=2


同样,当对Activity对象进行检测,Activty对象内存泄漏的时候,便会在log当中输出如下内容:

05-17 09:45:24.835: E/StrictMode(566): class com.alipay.StrictModeDemoActivity;instances=2; limit=1

05-17 09:45:24.835: E/StrictMode(566):android.os.StrictMode$InstanceCountViolation: classcom.alipay.StrictModeDemoActivity; instances=2; limit=1

目前,StrictMode给我们提供了两大类的策略,一类是对于当前线程的监控(Disk Reads、Network access等),另外一类是关于VM虚拟机等方面的监控策略(内存泄漏的Activity对象和SQLite对象)。

但通过项目实践,发现如果想通过StrictMode来保证代码的质量,是远远不够的,一是StrictMode检测到策略违背时输出的log日志包含的信息是有限的,二是现在给我们提供的检测策略种类还不够多。但是值得欣慰的是,从API Level10到15,我发现Google也在不断的完善StrictMode这个工具类,相信在不久的将来它的作用一定会越来越重要。


二、ADT自带的Lint工具

在Eclipse的ADT插件更新到最新的16.0及以上版本,内部集成了一个名为Lint的工具。Lint工具能够专门针对Android工程项目进行全面的分析,包括项目内的资源文件、布局文件和静态代码进行检查,检查结果如下图:



下面列举一些项目检查过程中发现的典型问题:

1)代码中的字符串没有进行全球化处理。

提示信息:"AboutVersionName" is not translated in en

2 不同命名的两个图片文件,具有相同的图片内容,资源冗余。

提示信息:The following unrelated icon files have identical contents: alipay_contact_normal.9.png, alipay_qrcode_normal.9.png

3)xml布局文件或描述文件当中的一些比较典型的警告信息

提示信息:The id "AlipaySubTitle" is not referring to any views in this layout

提示信息:<uses-sdk> tag appears after <application> tag

4)布局文件的优化

提示信息:This <Framelayout> can be replaced with a <merge> tag

5)代码的高效性

用Android API中性能更好的SparseArray来代替HashMap。

Use new SparseArray<String>(...) instead for better performance

6)低性能的源代码:

mBackImgMap.put("0",new Integer(R.drawable.basic));

优化之后的源代码:

mBackImgMap.put("0",Integer.valueOf(R.drawable.basic));

最好不要直接调用包装类的构造函数,而用valueOf方法来替代他,这样有助于程序更高效的执行。

提示信息:Use Integer.valueOf(R.drawable.basic) instead

7)避免在manifest.xml文件中对debug属性进行硬编码,

提示信息:Avoid hardcoding the debug mode; leaving it out allows debug and release builds to automatically assign one

美中不足的是eclipse插件形式的Lint工具还没有导出错误报告的功能。



三、JAVA代码质量检测工具PMD

最后一个介绍的工具是PMD,相对于前两种代码质量检测工具,它不是专门给android编程定制的工具,PMD最大的优势在于它能够依据java通用的编码规范检测出代码当中编码不规范的地方,在通用的编码过程中,它的作用明显要比前两种工具更广泛,而且检查更加严格。

首先在自己的电脑中安装PMD工具(我安装的是eclipse的PMD插件,推荐大家以这种方式来安装,用起来更加傻瓜式一些,当然专家级的朋友可以安装PMD的独立客户端,详细资料请参考http://pmd.sourceforge.net/rules/java/strictexception.html)。

下面结合当前项目中的部分实际代码来进行对PMD工具的实践:

在eclipse中选中当前项目,点击右键->PMD -> check code with PMD

就会在项目源码中加入不规范的提示信息,我们也可以以报告的形式导出这些不规范的编码列表,当然导出报告的形式有多种,如下图reports文件夹:



下面结合代码当中的一些不规范代码来进行具体说明:

1)sourceCode:packagecom.alipay.android.appHall;

problem: src/com/alipay/android/appHall/AppHall.java:1 Package name contains upper casecharacters

包的命名需要用小写字母。

2)sourceCode:

public void onItemClick(AdapterView<?>parent, View arg1, int index, long arg3) {

AppItemInfo itemInfo = mAppItemInfos.get(index);

itemInfo.onClick(mContext);

}

problem: src/com/alipay/android/appHall/AppHall.java:43 Local variable 'itemInfo' could bedeclared final

局部变量itemInfo可以声明为final。

3)sourceCode:

public static intgetDensityDpi(Context context) {

DisplayMetrics displayMetrics = getDisplayMetrics(context);

returndisplayMetrics.densityDpi;

}

problem:src/com/alipay/android/appHall/Helper.java:176 Parameter'context' is not assigned and could be declared final

因为参数context没有在方法内做任何改动,参数类型可以声明为final。

4)sourceCode:

catch (Exception e){}

problem:src/com/alipay/android/appHall/Helper.java:290 Avoidempty catch blocks

捕获异常后没有做任何处理。

5)Helper类的getConfigInfo()方法,非常复杂

problem:src/com/alipay/android/appHall/Helper.java:317 Themethod 'getConfigInfo' has a Cyclomatic Complexity of 17.

getConfigInfo()方法过于复杂,PMD工具明确规定了方法和类的复杂度,当超过时就会报出警告信息。(PMD对于一个类的方法和属性的数量也做了明确的规定,一个类的方法或者属性过多都会被警告)

6)sourceCode: ArrayList<UIInterface>mdelayGetValueGroup=new ArrayList<UIInterface>();

problem:src/com/alipay/android/appHall/NormalPage.java:53 Avoid using implementation types like 'ArrayList'; use theinterface instead

用抽象的接口来代替具体的类。

7) sourceCode:

if (resultCode == Activity.RESULT_OK){

if (appRunTime.doServiceCallback(null))

return;

}

problem:src/com/alipay/android/appHall/NormalPageFrame.java:114 These nested if statements could be combined

两次if判断可以合并成一个来处理,更加简洁。

8) sourceCode:int index =snapshotQrCode.indexOf(":");

problem:src/com/alipay/android/appHall/NormalPageFrame.java:168 String.indexOf(char) is faster than String.indexOf(String).

用字符类型的参数比用字符串类型的参数更加高效。

9) sourceCode: System.out.println("REQUEST_CODE_QRCODEaccount=......");

problem:src/com/alipay/android/appHall/NormalPageFrame.java:174 System.out.print is used

程序中用到了控制台输出语句,大量的输出语句如果在发布的版本中执行,会极大的影响软件的运行效率,通过PMD我们可以定位源码中所有用到的输出语句,并将其清除。

10)sourceCode:

if (runTimeTimerMap ==null ||runTimeTimerMap.size()== 0) {

return;

}

problem:src/com/alipay/android/appHall/NormalPageFrame.java:351 Substitute calls to size() == 0 (or size() != 0) with calls toisEmpty()

isEmpty()方法比 size() == 0 (or size() != 0)更加高效。

11)另外,在代码质量的分析过程中,发现有大量的地方应该用final关键字,代码中都没有使用,几乎在一半以上的类中都多次出现了这个问题,以下两种情况出现的最多,在这里稍微总结下:

a.当方法当中声明的字段内容在初始化后不会再进行修改,便可以在声明这个字段的时候加上final关键字。

b.当类中一个成员变量的初始化,只需在这个成员变量声明的时候或者在这个类的构造函数内初始化的时候,这个成员变量可以在声明的时候加上final关键字。

四、小结

以上介绍的三种java代码检测方法各有特点,StrictMode是一种轻量级的代码检测方式,对于磁盘的读写、联网以及Activity对象的内存泄漏等几种比较严重的错误进行检测。Android开发工具当中自带的Lint工具更加专业,能够针对Android项目当中的冗余资源文件进行扫描(第一次扫描项目时竟然检测出了大约80K冗余图片资源),布局文件当中的不合理地方进行提醒,还能根据Android SDK的特性对于项目当中的静态代码进行检查,提示出Android平台特有的更佳高效的实现方式。而PMD工具更加侧重于以业内标准的JAVA编码规范对项目内的静态JAVA代码进行检查,而且检查的力度更加严格,更具有规范性。

但无论以上的哪一种方式,都不是完美的,用以上的几种方法进行代码质量检查,从检测结果中我们可以看到,最终的问题报告都包含了大量的编码问题,我们需要对这些报告的结果进行人工帅选,把那些有价值的问题进行研究并在项目中加以修正,这才是最最重要的一个环节。


备注:如果大家有更好的代码检测工具或者方法,可以给我留言,也可以发我邮箱qian.zqzq@alipay.com,我会及时的更新与大家一起分享。


更多相关文章

  1. tcping测试服务器TCP端口
  2. Android逆向之旅---静态分析技术来破解Apk
  3. 如何解决恶意APK中常见的Native代码加壳保护
  4. android中使用ViewPager实现图片左右拖动
  5. ListView飞入加载item及滑动删除item
  6. Android项目管理之数据库升级策略
  7. Android(安卓)Studio中布局文件(如activity_main.xml)设计视图&代
  8. 如何用手机访问电脑本地 localhost 网页或者服务器, 以调试web项
  9. android 项目练习:自己的词典app——生词本(一)

随机推荐

  1. numpy无法将值分配给列的一部分
  2. python及其模块下载集合
  3. 在python中出现搜索项的打印行
  4. python基础编程_12_日期格式的使用和转换
  5. 从零开始部署Django生产环境(适用:《跟老齐
  6. python python 入门学习之网页数据爬虫cn
  7. AttributeError:'Flask'对象没有属性'logi
  8. UnicodeDecodeError: 'gb2312' codec can
  9. python输出斐波那契数列三角形
  10. 是否有一个类似于Python的“枚举”函数的