當一個項目在不斷開發迭代、功能累加的過程當中,重複代碼的出現幾乎是不可避免的。其出現的緣由不外乎如下兩點:javascript
因此對項目按期進行代碼率檢測是一個頗有意義的事,能夠幫助開發人員發現冗餘代碼,進行代碼抽象和重構。php
本文將介紹代碼重複率檢測的基本概念以及前端、客戶端項目中代碼重複率檢測的實踐過程。css
在《Software Clone Detection and Refactoring》一文中,對重複代碼的類型進行了定義:html
很明顯越日後,重複代碼檢測難度越大。在實際狀況中,咱們的檢測要求只要大體能知足前二者就已經足夠了。前端
在技術上,重複代碼檢測主要有如下分類:vue
這些技術細節不是本文關注的重點,有興趣的讀者能夠查閱相關論文進行詳細瞭解。java
因爲前端源代碼文件格式多樣,重複率檢測除了源碼檢測之外,還能夠從檢測打包文件和文件退化角度考慮。node
檢測前端代碼重複率的工具備jsinspect、jscpd,PMD-CPD(PMD's Copy/Paste Detector)中也支持js文件的重複率檢測。python
每一個工具各有其優缺點,若只須要檢測js或jsx文件,且對檢測結果要求較高,能夠選擇jsinspect或者PMD-CPD工具,若考慮檢測工具的通用性,能夠選擇jscpc工具。linux
通過分析
爲了適應多種前端代碼文件,本團隊目前選擇jscpd做爲前端代碼重複率檢測工具。對於重複率要求較嚴格的項目,可使用jsinspect針對js(x)文件進行進一步檢測。
jscpd工具能夠在本地使用,也能夠集成在gulp中。
npm install jscpd -g
複製代碼
.cpd.yaml
文件,配置參考#.cpd.yaml
languages:
- javascript
- typescript
- jsx
- vue
- css
files:
- 'src/**'
- 'less/**'
exclude:
- 'dist/**'
- 'dest/**'
- 'neurons/**'
- 'node_modules/**'
- 'test/**'
- 'data/**'
- 'css/**'
- 'entries/**'
reporter: xml
xsl-href: '/Users/dianping/dp/f2e-cpd/reporters-xslt/simple.xsl'
limit: 100
min-tokens: 70
min-lines: 5
output: '/Users/dianping/dp/f2e-cpd/report-ecom-70.xml'
複製代碼
其中languages值對應的文件後綴以下:
TokenizerFactory.prototype.LANGUAGES = {
javascript: ['js', 'es', 'es6'],
typescript: ['ts', 'tsx'],
jsx: ['jsx'],
haxe: ['hx', 'hxml'],
coffeescript: ['coffee'],
ruby: ['rb'],
php: ['php', 'phtml'],
python: ['py'],
css: ['less', 'css'],
sass: ['scss'],
java: ['java'],
csharp: ['cs'],
go: ['go'],
clike: ['cpp', 'c', 'm', 'h'],
htmlmixed: ['html', 'htm'],
yaml: ['yaml', 'yml'],
erlang: ['erl', 'erlang'],
swift: ['swift'],
xml: ['xml', 'xsl', 'xslt'],
puppet: ['pp', 'puppet'],
twig: ['twig'],
vue: ['vue']
};
複製代碼
命令行工具 全部配置參數也能夠直接在終端命令行中以參數形式附加。
查看結果 執行jscpd
命令行,在終端能夠看到簡要的重複代碼位置,以及總的重複率計算結果。指定verbose
參數,能夠看到重複代碼塊。
jscpd支持輸出xml和json兩種格式的報告文件,爲了便於查看重複代碼塊,建議輸出xml格式文件,配置xsl模板後在瀏覽器中具備較高的可讀性。
npm install gulp-jscpd
複製代碼
var jscpd = require('gulp-jscpd');
gulp.task('jscpd', function() {
return gulp.src([path.join(__dirname, 'src/**'), path.join(__dirname, 'less/**')])
.pipe(jscpd({
'min-lines' : 5,
'min-tokens': 70,
reporter : 'xml',
languages : ['javascript', 'jsx', 'css'],
output : '/Users/dianping/dp/f2e-cpd/report-ecom-70.xml',
verbose : false,
debug : false,
silent : false,
failOnError : false,
'xsl-href' : '/Users/dianping/dp/f2e-cpd/reporters-xslt/simple.xsl'
}));
});
複製代碼
對於客戶端代碼而言,因爲有iOS和Android兩個平臺,因此須要考慮工具的通用性,必須支持objective-C和java兩種語言。
基於以上緣由,最後選擇的工具是PMD-CPD(PMD's Copy/Paste Detector)。此工具使用的是Karp-Rabin字符串匹配算法,支持gui,支持命令行,輸出格式支持text、xml、csv等,能夠很好的配合腳本語言進行二次開發,對重複率數據進行統計。
./run.sh cpdgui
複製代碼
./run.sh cpd --minimum-tokens 100 --files /usr/local/java/src/java --language java --format xml
複製代碼
工具的使用自己是比較簡單的,更多的是針對不一樣項目進行相應的定製。可能須要考量的點有以下幾個:
tokens和有效率的平衡: tokens是工具的一個參數,能夠理解爲對重複代碼長度定義的標準。因此當tokens越小,檢查到的重複代碼數量更多、覆蓋面越大,但相應的有效率就會下降,產生較多的誤報狀況。反之則有效率較高,但覆蓋率就會相應下降,會有所遺漏。對tokens的選擇依賴於項目的語言、框架等因素,在工具使用初期能夠進行屢次測試比較肯定合適的tokens值。
腳本定製:使用其餘腳本語言例如python、ruby等進行相應的定製,把代碼重複率檢查包裝成爲一個自動化工具。重複率檢查工具例如PMD-CPD自己也不具有統計功能,因此腳本還能夠幫助把最後的檢查結果進行量化。
重複率標準:對於比較獨立、規模不大的項目,剛開始檢查時,5%多是一個比較合適的值。固然重複率標準的制定須要參考的因素有不少,例如tokens、項目、架構、時間等等。
Fontana F A, Zanoni M, Ranchetti A, et al. Software Clone Detection and Refactoring[J]. Isrn Software Engineering, 2013, 2013(2013).