文档章节

重复代码-数据分析

开源中国驻成都办事处
 开源中国驻成都办事处
发布于 2014/03/26 12:27
字数 1366
阅读 158
收藏 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
SonarQube 解决了代码追踪问题

通过不断分析代码以了解潜在的质量问题,开源的 SonarQube 项目支持了 DevOps 的“尽早发布和经常发布” 的思维模式。 越来越多的组织正在实施 DevOps 以便在通过中间开发和测试环境以后更快...

问题终结者
11/23
0
0
使用 SonarQube 追踪代码问题

通过不断分析代码以了解潜在的质量问题,开源的 SonarQube 项目支持了 DevOps 的“尽早发布和经常发布” 的思维模式。 越来越多的组织正在实施 DevOps 以便在通过中间开发和测试环境以后更快...

作者: Sophie Polson
11/14
0
0
python求职Top10城市,来看看是否有你所在的城市

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

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

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

开开心心过
2015/08/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

nginx中部署vue打包后的静态文件

如何在nginx中部署静态资源就不描述了, 请看我的这篇博客 将vue脚手架项目打包后的静态文件放到nginx上, 发现有个问题, 即url上有#, 怎么去掉这个#呢. 1 项目中router的mode 路由的mode要为h...

克虏伯
9分钟前
1
0
JS容易理解错误的地方

在这端代码执行的末尾,你会不会hi变量回事函数中的hi了?你会不会认为这不是按引用传递了? 对值传递和引用传递产生质疑了? 1 var hi = {};2 function sayHello(hi) { ...

器石_
10分钟前
0
0
Java开发学习--MongoDB

之前只学过sql,第一次使用非关系型数据库。以前对于关系型数据库与非关系型数据库的概念很模糊,通过这次的学习对这两者有了一个清晰的概念。 主键 在MongoDB中,主键名叫"_id",如果在生成...

微笑向暖wx
14分钟前
0
0
Java8-2-Lambda表达式实战-一句话实现Map中按照Value排序

今天我们来实战一把, 对Map的Value值排序进行简化. 如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群...

编程SHA
17分钟前
0
0
Vue中img的src属性绑定与static文件夹

1、其中有一个叫做static的文件夹,尝试将logo.png放入这个文件夹,然后修改imgUrl: imgUrl = '/static/logo.png' 成功读取到了logo.png. 执行npm run build后查看dist文件,发现logo.png原...

小黑202
18分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部