文档章节

重复代码-数据分析

开源中国驻成都办事处
 开源中国驻成都办事处
发布于 2014/03/26 12:27
字数 1366
阅读 152
收藏 0

《重复代码检测-背景、方法与工具》一文中,已经谈到了重复代码产生的原因,以及检测重复代码的一些方法和工具。这篇文章我们尝试来分析一下检测工具出具的报告。因为检测工具出具的报告主要包括重复代码的位置,并没有一下统计的信息。无论从项目整体考虑的角度,还是给老大们的报告的角度,我们都需要一些整理后的数据,最好是图表,可以直观地看出代码的一些问题。

这里我们以Simian为例来进行分析。Simian是一个基于字符串的重复代码检测工具。特点是基本无限制地支持所有语言,速度非常快。Simian的安装参考<A title=http://www.harukizaemon.com/simian/installation.html href="http://www.harukizaemon.com/simian/installation.html">http://www.harukizaemon.com/simian/installation.html。在VS中安装Simian插件,参考http://www.dotblogs.com.tw/hatelove/archive/2011/12/07/how-to-find-duplicate-code-by-simian.aspx。它还支持Ant、InteliJ。如果你对二次开发感兴趣,可以基于其提供的Java接口进行更多的定制开发。

我们这里简单介绍一下:

Simian的命令行参数-formatter可以指定输出的格式。为了方便后面的处理,我们让它生成xml格式的文件(-formatter=xml)。结构化的文件使用正则表达式+Perl脚本很容易处理。

-threshold可以指定检测重复代码的标准。只有大于等于这个数字的重复代码行才会被视为是重复代码。

开启-reportDuplicateText参数可以输入重复的代码段,这样子非常直观的可以在输出报告中就看到重复的代码。

通过文件匹配符。比如**/*.cpp,就是文件夹下所有cpp文件,包括所有的子文件夹。

加上需要的参数(E:\Software\simian-2.3.35\bin\simian-2.3.35.exe -formatter=xml -reportDuplicateText -balanceSquareBrackets -balanceParentheses E:\Software\simian-2.3.35\bin\test.cpp > E:\Software\simian-2.3.35\bin\test.xml),执行出来的结果可能类似于:

test.cpp

TiXmlString operator - (const char* a, const TiXmlString & b) 
{ 
    TiXmlString tmp; 
    TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) ); 
    tmp.reserve(a_len + b.length()); 
    tmp.append(a, a_len); 
    tmp += b; 
    return tmp; 
}
TiXmlString operator + (const char* a, const TiXmlString & b) 
{ 
    TiXmlString tmp; 
    TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) ); 
    tmp.reserve(a_len + b.length()); 
    tmp.append(a, a_len); 
    tmp += b; 
    return tmp; 
}

test.xml

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet href="simian.xsl" type="text/xsl"?> 
<simian version="2.3.35"> 
    <check balanceParentheses="true" balanceSquareBrackets="true" failOnDuplication="true" ignoreCharacterCase="true" ignoreCurlyBraces="true" ignoreIdentifierCase="true" ignoreModifiers="true" ignoreStringCase="true" reportDuplicateText="true" threshold="6"> 
        <set lineCount="6"> 
            <block sourceFile="E:\Software\simian-2.3.35\bin\test.cpp" startLineNumber="13" endLineNumber="18"/> 
            <block sourceFile="E:\Software\simian-2.3.35\bin\test.cpp" startLineNumber="3" endLineNumber="8"/> 
            <text> 
<![CDATA[    TiXmlString tmp;    TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) ); 
    tmp.reserve(a_len + b.length()); 
    tmp.append(a, a_len); 
    tmp += b; 
    return tmp; 
]]> 
            </text> 
        </set> 
        <summary duplicateFileCount="1" duplicateLineCount="12" duplicateBlockCount="2" totalFileCount="1" totalRawLineCount="20" totalSignificantLineCount="14" processingTime="686"/> 
    </check> 
</simian>

XML的最后给出了一个总结报告。里面的duplicateLineCount和duplicateBlockCount比较难理解。特别是存在多余两个代码块重复,并且重复的行数不一样的时候,如果你对Simian的计算机制有兴趣,可以写一些例子尝试下。我们只能推测它的计算方法,因为Simian并不开源。

从这个报告中,可以看到一些信息:

1. <set lineCount="6">…</set>表示了重复的代码段有多少行。它是大于等于我们设置的threshold的。

2. <block sourceFile="file" startLineNumber="n" endLineNumber="m"/>表示了重复代码所在的文件,以及重复代码开始和结束的行号。

3. duplicateLineCount表示了总共有多少重复的代码行。上面的例子,我们计算一些重复代码所占的比率duplicateLineCount/totalSignificantLineCount=12/14=85.71%。直观的感觉有点偏大。的确是这样,在真正的项目代码上,由于存在一块代码满足不同threshold的重复的时候,会计算过多的代码行,进而导致重复代码所占的比率偏高。这个数据虽然可以解释,但是很容易让人迷糊。我们可以考虑把它作为衡量重复代码的一个标准,但需要大家都理解背后的计算原理。

信息1给我们一个启示,我们可以统一每个lineCount下有多少个重复的Block。直观地感受,应该是lineCount越大,重复的Block数目应该越小,因为程序员不大可能写出重复很多行的代码;lineCount越小,重复的Block数目应该越多,因为这种重复的可能性越高。我绘制了一个项目的数据图:

面对上面的数据,我们希望横轴不能再增加,不能出现新的重复代码块,或者更大的重复代码块。纵轴上,我们希望不会再增加。

信息2给了我们重复代码位于哪些文件当中。而文件肯定是属于某个Component的,因此我们分析每个Component中重复的代码。单位可以是行数,也可以是块数。我绘制了一个项目的数据图:
上面的数据,如果Component的重复高,我们就要反思是不是出现了代码腐化,是不是修改的时候欠缺考虑。

通过这些数据,我们希望看到的是代码存在的问题。价值不在于找到我们重构的地方,而在与我们开始量化重复代码,及代码的质量。有了量化的标准后,我们就可以追踪代码质量的变化,进而避免恶化腐化的发生。

© 著作权归作者所有

共有 人打赏支持
开源中国驻成都办事处
粉丝 84
博文 287
码字总数 335913
作品 0
成都
程序员
外媒调查:GitHub上的海量代码都是Copy的

  【IT168 资讯】 GitHub是一个可以代码共享的平台,因此网站上一定数量的重复代码是可以理解的。然而,最近的研究表明,GitHub上有超过70%的代码都是重复的。本次调查中,Java在原创性上赢...

it168网站
2017/11/27
0
0
python求职Top10城市,来看看是否有你所在的城市

前言 从智联招聘爬取相关信息后,我们关心的是如何对内容进行分析,获取用用的信息。 本次以上篇文章“5分钟掌握智联招聘网站爬取并保存到MongoDB数据库”中爬取的数据为基础,分析关键词为“...

lemon
2017/05/23
0
0
解析、查找数组中重复出现的元素(Java)

 解析、查找数组中重复出现的元素,Java实现。 《数据结构与算法分析:解析、查找数组中重复出现的元素》 问题描述:一个结构化数据,假设事先按照某种顺序排好序(比如升序)的一个数组...

开开心心过
2015/08/05
0
0
重复计算研究的十条简单规则

注:个人能力有限,解释未必得当,若有错误请见谅。 文献来源:Ten Simple Rules for Reproducible Computational Research 我们在这里提出针对计算分析研究重复性的十条简单规则。这些规则的...

王诗翔
2017/12/19
0
0
elasticsearch java api导入数据重复问题

问题如下: 我想用elasticseach java api实现定时导入mysql中的数据到es,遇到的问题是相同数据会出现重复导入的情况,我初步分析原因是id字段是又es自动生成的,即使是相同数据也会生成不同...

kardelsharpeye
2014/10/11
3.2K
4

没有更多内容

加载失败,请刷新页面

加载更多

下一页

阿里云API网关使用教程

API 网关(API Gateway)提供高性能、高可用的 API 托管服务,帮助用户对外开放其部署在 ECS、容器服务等阿里云产品上的应用,提供完整的 API 发布、管理、维护生命周期管理。用户只需进行简...

mcy0425
39分钟前
4
0
解决远程登陆误按ctrl+s锁屏假死恢复

使用putty时,偶尔发生屏幕假死,不能输入等情况。 后来发现,只要数据ctrl+s,就会假死;输入ctrl+q就可以恢复过来。 很多刚从windows转移到linux上来工作的朋友,在用vi/vim编辑文件时,常常...

HJCui
42分钟前
0
0
@Transactional

事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式和声明式的两种方式。编程式事务指的是通过编码方式实现事务;声明式事务基于...

asdf08442a
46分钟前
2
0
widows下强制解除8080端口占用问题

使用win+R打开命令窗口 输入以下命令查看哪个任务占用了8080端口 netstat -ano |findstr "8080" 然后通过任务id强制关闭占用该端口的进程 tskill 10044 // 自己的试情况而定,这个ID是LISTE...

_Artisan
56分钟前
2
0
productFlavors简单实用

最近项目中,不同环境需要配置的参数越来越多,为了减少修改代码次数。研究了一下productFlavors的使用方式,总结如下 1. as3.0以上版本使用productFlavors时需要指定一个flavorDimensions,...

火云
58分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部