黃子杰 ,陳軍華 ,高建華
1(上海師范大學(xué) 計算機(jī)科學(xué)與技術(shù)系,上海 200234)
2(華東理工大學(xué) 計算機(jī)科學(xué)與工程系,上海 200237)
JavaScript(簡稱JS)是一種使用弱類型和動態(tài)類型的解釋型編程語言,JS 程序的結(jié)構(gòu)和變量類型在運(yùn)行時才會明確,因此,大量為Java 等強(qiáng)類型語言設(shè)計的靜態(tài)分析手段難以奏效,導(dǎo)致其代碼質(zhì)量缺乏工具保障.同時,它還包含諸多增強(qiáng)語言靈活度(flexibility)的特性,例如原型鏈、閉包、頭等函數(shù)等,它們形成了復(fù)雜的代碼組件繼承、組合方式.因此,編寫JS 程序頗具挑戰(zhàn)性,期間易產(chǎn)生Code Smell 和Bug[1,2].
Code Smell 是軟件程序中存在不良設(shè)計和不良實(shí)現(xiàn)的征兆[3],其強(qiáng)度可由度量指標(biāo)(metric)量化.正確地檢測和量化Code Smell 可以指導(dǎo)軟件重構(gòu),提高軟件的可用性和可靠性.
然而,現(xiàn)有Code Smell 度量不足以理解JS 程序的復(fù)雜性和程序質(zhì)量,常見的Code Smell 度量很少被JS 相關(guān)的研究使用[4],需對其進(jìn)行開發(fā)或改進(jìn),以適應(yīng)JS.目前已出現(xiàn)面向JS 的Code Smell 檢測工具,例如SonarQube,JSNose[1],它們僅面向微觀層面上(即函數(shù)、語句)的內(nèi)聚或耦合問題.
JSNose 主要討論了函數(shù)、代碼塊及對象內(nèi)部的Code Smell,并引入了3 種通用類Code Smell 的檢測方式來檢測對象內(nèi)部的問題,例如過大對象和不當(dāng)?shù)睦^承,但研究不涉及多個對象間的設(shè)計問題.研究還提及了一種文件層面的Code Smell,它面向JS,HTML 和CSS 這3 種語言在代碼中混寫的耦合問題.Saboury 等人[5]根據(jù)語言標(biāo)準(zhǔn)的新變化,擴(kuò)充并修正了JSNose 的定義,此類修正主要發(fā)生在語法和語句層面上,涉及作用域和閉包等問題.該研究還就Code Smell 對JS 代碼易錯性(fault-proneness)的影響排序,結(jié)果顯示,部分涉及不當(dāng)賦值的Code Smell 更易引發(fā)程序錯誤.
上述微觀研究可以提出程序?qū)崿F(xiàn)的重構(gòu)建議、局部提升程序的質(zhì)量,但無法有效分析粒度更大的(例如類、模塊)設(shè)計問題.Palomba 等人[6]發(fā)現(xiàn):因?yàn)榇罅6鹊拇a組件過于復(fù)雜,模塊和類層面的Code Smell 相比函數(shù)Code Smell 更難被有效地識別,解決這類問題的效率和成功率極低,因此需要理論和工具輔助.
類(class)是JS 的一種常見設(shè)計模式,在Silva 等人[7]抽選的60 個JS 程序樣本中,68%使用了類,34%較頻繁或頻繁地使用了類.優(yōu)秀的類設(shè)計體現(xiàn)為高內(nèi)聚和低耦合[8],內(nèi)聚(cohesion)和耦合(coupling)可用于衡量面向?qū)ο蟪绦蚬δ芊植嫉暮侠硇?內(nèi)聚是軟件組件內(nèi)功能的關(guān)聯(lián)程度,耦合是軟件組件間交互的頻繁程度.
由于JS 類的信息檢測存在困難,導(dǎo)致部分Code Smell 的通用檢測方法難以復(fù)用,因此Code Smell 的相關(guān)工作仍未充分涉及JS 類的常見設(shè)計問題.提出一個JS 類的內(nèi)聚耦合Code Smell 檢測方式是迫在眉睫的任務(wù).
本文的主要貢獻(xiàn)為:
(1) 結(jié)合代碼的文本和結(jié)構(gòu)信息,提出了一個檢測JS 類的內(nèi)聚耦合Code Smell 的靜態(tài)分析方法JS4C,它可以量化Blob、Feature Envy(簡稱FE)和Dispersed Coupling(簡稱DC)這3 種Code Smell,并檢測JS開源軟件中的內(nèi)聚耦合問題.
(2) 細(xì)化并改進(jìn)了類耦合Code Smell 的檢測方式:首先,根據(jù)耦合、內(nèi)聚的設(shè)計問題對Fowler 定義的22種Code Smell 進(jìn)行了分類,對比并區(qū)分了FE 的兩類檢測方式;其次,引入了DC 細(xì)化耦合問題檢測的粒度,改進(jìn)了其CDISP 度量,以適應(yīng)JS 的弱類型語言特性.
(3) 指出了文本信息源對JS Code Smell 檢測的重要性.實(shí)驗(yàn)發(fā)現(xiàn),引入文本特征可以提升Code Smell 的檢測效果.
本文第1 節(jié)介紹本文所涉研究領(lǐng)域的相關(guān)工作以及其中存在的困難和問題.第2 節(jié)介紹本文所涉3 種Code Smell,簡述檢測的各個階段,包括預(yù)處理、檢測和結(jié)果輸出,是對檢測流程的概覽.第3 節(jié)研究3 種Code Smell的文本和結(jié)構(gòu)方式檢測算法,并給出一個綜合判定策略.第4 節(jié)給出實(shí)驗(yàn),以驗(yàn)證檢測結(jié)果的準(zhǔn)確性,并探究對檢測準(zhǔn)確性造成負(fù)面影響的因素.最后得出結(jié)論,并討論今后的工作.
圖1 為3 個擁有相同屬性和方法的Rental 類,圖1(a)的程序是一個Java 類,其余兩段程序?yàn)镴S 類,JS 類的實(shí)現(xiàn)參考了Fowler 的影音店案例[9,10]和JS 類檢測的文獻(xiàn)[7].
Fig.1 Demonstration code showing Java and JS class implementations圖1 Java 和JS 類的實(shí)現(xiàn)代碼示例
JS 類是基于JS 原型繼承(prototype-based inheritance)構(gòu)建的一種經(jīng)典模型[11],它的實(shí)現(xiàn)可分為兩類[12].
(1) 在早于ES2015 的語言標(biāo)準(zhǔn)中,類是基于函數(shù)的設(shè)計模式,實(shí)現(xiàn)方式不唯一,圖1(b)是一種常見的實(shí)現(xiàn).
(2) 如圖1(c),ES2015 及更新的標(biāo)準(zhǔn)用糖衣語法(syntactic sugar)簡化了類的實(shí)現(xiàn)方式.
檢測JS 類首先需要定位構(gòu)造器(constructor,例如圖1 中的灰色高亮部分)和成員屬性(例如_data),再遍歷函數(shù)的原型鏈(例如圖1(b)的Rental.prototype)搜索其成員函數(shù)和子類.構(gòu)造器是類的顯著特征,可用于創(chuàng)建對象.定位構(gòu)造器,可通過查找類的實(shí)現(xiàn)函數(shù),或查找構(gòu)造器的調(diào)用語句(例如new 語句).目前,已有效果較好的、基于抽象語法樹遍歷的開源JS 類檢測工具JSDeodorant[13]、JSClassFinder[7].
本文需要檢測的JS 類信息為類的成員(即函數(shù)和屬性)、類的函數(shù)及其簽名、類引用的外部數(shù)據(jù)提供者(foreign data provider,簡稱FDP)和類引用的內(nèi)部成員.某類的“外部數(shù)據(jù)”指的是軟件系統(tǒng)中非本類的類成員.分析引用關(guān)系,可通過遍歷代碼中的訪問操作(access)實(shí)現(xiàn).訪問操作是指對對象的引用、對其成員屬性的引用(reference)或?qū)ζ涑蓡T函數(shù)的調(diào)用(call).
檢測JS 類及相關(guān)信息的挑戰(zhàn)包括:
(1) 檢測難以適用于所有的類實(shí)現(xiàn)方式.實(shí)現(xiàn)類的設(shè)計模式,有至少5 種較為常用的、適用于不同版本語言標(biāo)準(zhǔn)的方式[7,13],給軟件組件的判定和標(biāo)準(zhǔn)化帶來困難.
(2) 檢測類與類間的關(guān)系困難.受JS 的語言特性限制,類成員屬性的類型在靜態(tài)分析過程中是未知的.類型信息的缺失,導(dǎo)致分析引用關(guān)系的困難.這種缺失無法使用動態(tài)分析完全彌補(bǔ),因其依賴爬蟲,不適用于運(yùn)行在服務(wù)端的JS 程序.
結(jié)構(gòu)分析是最常見的Code Smell 檢測方法,通常包括2 個階段,即信息收集和檢測判定:在信息收集階段,分析工具通過遍歷抽象語法樹獲取檢測對象的結(jié)構(gòu)信息;在檢測判定階段,需要根據(jù)度量的定義將收集得到的信息計算為度量值,再依據(jù)規(guī)則判定是否存在Code Smell.規(guī)則根據(jù)Code Smell 的定義設(shè)計,它通常由一系列度量閾值條件構(gòu)成,規(guī)則也可以包含其他非數(shù)值型特征(例如函數(shù)名等文本特征)[14].
本文檢測3 種Code Smell,包括Blob,FE 和DC.Blob 體現(xiàn)低內(nèi)聚,其余二者體現(xiàn)高耦合,定義分別為:
(1) Blob 表現(xiàn)為一個類,它實(shí)現(xiàn)了系統(tǒng)中的多種不同職責(zé)、體積龐大且復(fù)雜,其函數(shù)間的內(nèi)聚性低[6,14,15].
(2) DC 表現(xiàn)為一個函數(shù),與其所在類相比,它更依賴多個非所在類的操作[16,17].
(3) FE 表現(xiàn)為一個函數(shù),與其所在類相比,它更依賴某個特定的、非所在類的操作[6,15].
根據(jù)軟件組件的粒度及設(shè)計問題類型,表1 給出了Fowler[9]定義的22 種Code Smell 的分類情況.其中,FE因同時涉及方法和類的耦合,故出現(xiàn)兩次.God Class 亦稱Blob,后文均使用Blob 的表述.
Table 1 Code Smell classification by the types of design problems and their granularity表1 以設(shè)計問題種類及其粒度為依據(jù)的Code Smell 的分類
Silva 等人[7]指出:JS 軟件項(xiàng)目極少使用類的繼承特性,在樣本中僅占8%.故本文僅討論與類繼承無關(guān)的Code Smell.Palomba 等人[18]提出,Refused Bequest 同Message Chains 以及FE 同Inappropriate Intimacy 具有極高的同現(xiàn)性.故本文不涉及Message Chains 和Inappropriate Intimacy.林濤等人[19]指出:Divergent Change 與Shotgun Surgery 矛盾對立、存在權(quán)衡關(guān)系,且其檢測過程需要對多版本進(jìn)行分析.故不列入研究范圍.Middle Man 是一種耦合Code Smell,表現(xiàn)為類代理(delegate)了過多其他類的操作,可視作FE 的一個特殊情況.
綜上,在表1 的22 種Code Smell 中,本文聚焦Blob 與FE.因FE 的量化標(biāo)準(zhǔn)不一,故需分類討論.根據(jù)表2,標(biāo)準(zhǔn)可分為兩類:其一,確定被檢類與一或多個類發(fā)生耦合,但不確定與其耦合的類;其二,確定被檢類與一個類發(fā)生耦合,并確定與其耦合的類.為了細(xì)化耦合問題的檢測,本文對FE 取后者的定義及檢測方式.為了覆蓋同多個類發(fā)生耦合情況,本文引入DC[16].
Table 2 Comparison of three Code Smells related to class coupling表2 3 種類耦合相關(guān)的Code Smell 對比
結(jié)構(gòu)分析的挑戰(zhàn),是由JS 語言特性和Code Smell 度量指標(biāo)的特性共同構(gòu)成的,它們包括:
(1) JS 的語言特性導(dǎo)致結(jié)構(gòu)分析所需的精確信息難以獲取,檢測耦合Code Smell 需要推斷類型或依賴其他信息源.
(2) 部分Code Smell 的量化標(biāo)準(zhǔn)不一.
(3) 類的Code Smell 檢測方式均針對以Java 為代表的非解釋型語言,對于JS,需要改進(jìn)部分度量.
文本分析與結(jié)構(gòu)分析的主要區(qū)別在于信息收集階段,前者不依賴或較少依賴抽象語法樹中的結(jié)構(gòu)信息,而是將源碼視作文本片段,并使用文本挖掘算法計算文本相似度等度量信息.
Palomba 等人[6,15,16]運(yùn)用結(jié)構(gòu)分析和文本分析,對Java 軟件項(xiàng)目的多個歷史版本進(jìn)行了挖掘,研究分析了兩種檢測方式獲取的Code Smell 強(qiáng)度,得出了其解決的難易程度、變化的趨向、產(chǎn)生的原因等性質(zhì).研究指出,基于結(jié)構(gòu)方式和文本方式的檢測算法互補(bǔ),文本方式是重要的信息源,將兩種信息源結(jié)合的工作較少.
因?yàn)榻Y(jié)構(gòu)分析方法在檢測JS 變量的類型信息時,所能獲取的信息遠(yuǎn)不如Java 項(xiàng)目詳實(shí),所以文本分析和結(jié)構(gòu)分析的互補(bǔ)對JS Code Smell 的檢測更為重要.
文本分析方法可分為有監(jiān)督和無監(jiān)督兩類.有監(jiān)督的文本分析需要額外的人工干預(yù)來預(yù)先標(biāo)注文本,以形成帶標(biāo)簽(Label)數(shù)據(jù)集,故不適用于Code Smell 的檢測.在無監(jiān)督的文本分析方面,Blei 等人[21]提出了潛在語義分析(LDA)算法,該算法被應(yīng)用于Bavota 等人[22]檢測Code Smell 的方法中;Le 等人[23]基于Google 開源的、運(yùn)用深度模型的Word2Vec 詞向量算法,提出了將文檔用向量表示的算法.
LDA 是一種常用的文檔主題生成式模型,包含詞、主題和文檔這3 層結(jié)構(gòu).LDA 使用詞袋模型表示一個文檔,并將一個文檔視作隱含主題的有限混合,其中的每個單詞由一個主題生成,文檔之間的關(guān)聯(lián)可以由主題間的關(guān)聯(lián)決定.LDA 具備比LSA 等基礎(chǔ)主題建模方法更強(qiáng)的擬合能力.
Word2Vec算法可利用神經(jīng)網(wǎng)絡(luò)語言模型訓(xùn)練過程中獲得的權(quán)重矩陣參數(shù),將詞語轉(zhuǎn)化為向量.Skip-gram是Word2Vec算法使用的一種語言模型,它根據(jù)當(dāng)前詞匯預(yù)測上下文.Skip-gram 模型共有3 層,即輸入層、隱藏層(hidden layer)、輸出層.神經(jīng)網(wǎng)絡(luò)通過調(diào)整隱藏層至輸入層、輸出層的權(quán)重矩陣進(jìn)行訓(xùn)練,調(diào)整訓(xùn)練的過程可概括為:假如若干詞具有近似的輸出,則可反推詞間具有較高的相似性.基于Skip-gram 模型,Mikolov 進(jìn)一步提出了Doc2Vec,它基于詞向量表示文檔向量.本文采用PV-DBOW(distributed bag of words version of paragraph vector)模型,其設(shè)計思想和Skip-gram 相近,即:通過預(yù)測文檔的內(nèi)容訓(xùn)練一個矩陣,此矩陣即為文檔矩陣.通過計算文檔矩陣間的余弦相似度,可獲取相似度特征.
檢測流程包括4 個階段:信息抽取階段、預(yù)處理階段、檢測階段、判定階段,如圖2 所示.
(1) 信息抽取階段:從軟件項(xiàng)目的開源社區(qū)獲取特定Release 版本的源碼,配置類檢測引擎的運(yùn)行參數(shù)后開始類的檢測.類檢測引擎基于JSDeodorant[13]改進(jìn),JSDeodorant 是開源JS 類檢測工具,文獻(xiàn)報告其平均表現(xiàn)可達(dá)到95%的精確率和98%的召回率.在此基礎(chǔ)上,本文借助Google Closure Compiler[24]分析源碼所得的JS 語句類型信息,通過擴(kuò)展對象類型推斷[25],實(shí)現(xiàn)對類信息的檢測.
(2) 預(yù)處理階段:本階段為檢測階段所需的輸入做準(zhǔn)備.對于結(jié)構(gòu)分析,需對檢測到的JS 類信息去重和計算頻次,以便用于度量指標(biāo);對于文本分析,需將文本標(biāo)準(zhǔn)化.文本標(biāo)準(zhǔn)化的具體流程如下:
? 分詞.對駝峰和下劃線命名方式的變量名進(jìn)行分詞,將所有英語字符都轉(zhuǎn)換為小寫形式.
? 去除停用詞.將與業(yè)務(wù)邏輯無關(guān)的保留關(guān)鍵字、英語停用詞、特殊字符等內(nèi)容剔除.
? 提取詞干.去除單詞的詞綴,得到其詞根.
(3) 檢測階段:本階段對輸入數(shù)據(jù)運(yùn)行檢測算法,并計算動態(tài)閾值,最終輸出值域?yàn)閇0,1]的強(qiáng)度值.其中,本文對FE 運(yùn)用了Fokaefs 等人[20]提出的檢測算法,對DC 運(yùn)用了經(jīng)改進(jìn)的非嚴(yán)格NSCDISP 度量,對Blob運(yùn)用了LCOM5 度量[26].在基于相似度的文本檢測方面,本文對FE 和Blob 的檢測使用了Doc2Vec算法[23],并以LDA算法的結(jié)果作為對照組.由于文本分析對DC 的檢測效果不佳,故未予采用.
(4) 判定階段:對于一個代碼片段,檢測階段可輸出多個強(qiáng)度值.根據(jù)Code Smell 之間的關(guān)聯(lián)和結(jié)構(gòu)和分析方法的特點(diǎn)、優(yōu)劣,本文提出了一種綜合判定策略,最終得出該代碼片段的Code Smell 的種類及值域?yàn)閇0,1]的強(qiáng)度值,強(qiáng)度值越高,Code Smell 越嚴(yán)重.
Fig.2 Code Smell detection process of JS4C圖2 JS4C 的Code Smell 檢測流程
Code Smell 檢測的傳統(tǒng)方法使用代碼的結(jié)構(gòu)信息作為信息源[6],圖3 展示了本節(jié)涉及的結(jié)構(gòu)信息和度量.
Fig.3 Overview of structural analysis圖3 結(jié)構(gòu)分析概覽
3.1.1 結(jié)構(gòu)方式檢測DC
Palomba 等人[16]對Java 的DC 檢測使用了CINT(coupling intensity,耦合強(qiáng)度)、CDISP(coupling dispersion,耦合分散度)和FDP(foreign data provider,外部數(shù)據(jù)提供類)這3 種度量.其中,CINT 為被檢測函數(shù)中經(jīng)去重的函數(shù)調(diào)用次數(shù),FDP 指標(biāo)用是所有被訪問的數(shù)據(jù)所屬類的去重集合.CDISP 的計算公式如式(1)所示.
由于JS 的語言特性限制了類型檢測,即便類型推斷可確定部分類型,也無法確定全部函數(shù)的入?yún)㈩愋秃蛿?shù)據(jù)訪問操作的變量類型.CINT 和CDISP 的計算都依賴類型判定,若不作改進(jìn),檢測難以進(jìn)行.
據(jù)此,本文提出非嚴(yán)格的NSCDISP(non-strict coupling dispersion),它的非嚴(yán)格是針對FDP 和CINT 必須精確檢測函數(shù)入?yún)?input parameter)的類型而言的.盡管引用的對象類型難以精確檢出,但類中的數(shù)據(jù)訪問操作總數(shù)和類的成員尚可明確,仍可利用以上信息得知引用操作的數(shù)量.
CDISP 的計算依賴FDP 和CINT.本文對CINT 的檢測不作改動,使用非嚴(yán)格的FDP 個數(shù)檢測方式:對于不涉及函數(shù)入?yún)⒌臄?shù)據(jù)訪問,沿用原FDP 的檢測方式,若無法檢測到所屬類,則將其視作一個單獨(dú)的FDP;對于涉及函數(shù)入?yún)⒌臄?shù)據(jù)訪問,則計算WRFDP.
WRFDP(FDPwith weighted reference)是面向入?yún)⑼獠恳脵?quán)重的度量,具體方式為:對于函數(shù)f,有入?yún)⒓螾f.計算f在所屬類中被調(diào)用的總次數(shù)ntc(number of total calls).遍歷Pf,對Pf的每個元素pfi,計算pfi被調(diào)用時入?yún)⑿螀⒌乃鶎兕悶橥獠款惖拇螖?shù)ncfp(number of calls as foreign param).計算ncfp 與ntc 比值,其值域在[0,1]之間.ncfp 計算的基本思路是:分析被檢函數(shù)的每次調(diào)用,若調(diào)用的入?yún)⒉辉从谒鶎兕?則計入ncfp.
對于被檢函數(shù)的每個入?yún)?均計算其WRFDP,如式(2)所示.
非嚴(yán)格的NSFDP 的計算公式如式(3)所示.
本文將非嚴(yán)格的NSCDISP 作為DC 的強(qiáng)度(intensity)值Idc,其計算公式為
NSCDISP 和CINT 的檢測閾值(文獻(xiàn)[16]中的HIGH)取系統(tǒng)檢測結(jié)果的平均數(shù)(AVG)與標(biāo)準(zhǔn)差(STDEV)之和[17],未達(dá)到閾值的相關(guān)度量值將被改為0,下同.
在計算出軟件系統(tǒng)內(nèi)的全部Idc后,對于該系統(tǒng)的全部函數(shù){f1,f2,f3,…,fi},可以得到一個集合SIdc={Idc(f1),Idc(f2),Idc(f3),…,Idc(fi)},對所得結(jié)果進(jìn)行Min-Max 標(biāo)準(zhǔn)化,使其值域落入[0,1]區(qū)間,得出最終的強(qiáng)度值集合NSIdc(normalized structural intensity),如式(5)所示.
3.1.2 結(jié)構(gòu)方式檢測FE
對于被檢類Ccurrent,遍歷系統(tǒng)的類全集C.對于C中的每個元素Ci,檢測Ccurrent對Ci成員(函數(shù)、屬性)經(jīng)去重后的訪問次數(shù)ai,并依據(jù)ai的值對C中的類從大到小排序,若排序第一的類Ctop不等價于Ccurrent,則判定存在FE.將Ccurrent對Ctop的成員訪問次數(shù)atop記為ATFM(access to foreign members),將Ccurrent對自身的成員訪問次數(shù)acurrent記為ATLM(access to local members),FE 的強(qiáng)度為式(6)[20].
若Ife>0,即可判定FE 存在.用類似第3.1.1 節(jié)的方式對所得結(jié)果進(jìn)行Min-Max 標(biāo)準(zhǔn)化,得到結(jié)果集合NSIfe.
3.1.3 結(jié)構(gòu)方式檢測Blob
利用結(jié)構(gòu)方式檢測Blob 有兩個角度:類的體積和類的內(nèi)聚性[26].前者根據(jù)代碼長度或類成員的總數(shù),后者采用LCOM5(lack cohesion of method 5)度量.由于本文的主題僅和內(nèi)聚、耦合相關(guān),且類體積相關(guān)的度量需指定固定的閾值,故不將類的體積納入檢測考慮的因素.
對于類C,獲取其函數(shù)成員總數(shù)k、屬性成員總數(shù)l、被訪問的自身成員(函數(shù)、屬性)經(jīng)去重后的總數(shù)a,定義LCOM5 為式(7),其值域在[0,2]間,檢測閾值取第三分位點(diǎn)(75%)的值[27].
用類似第3.1.1 節(jié)的方式對所得結(jié)果進(jìn)行Min-Max 標(biāo)準(zhǔn)化,得到結(jié)果集合NSIblob.
圖4 展示了文本分析的方式,以經(jīng)文本標(biāo)準(zhǔn)化引擎處理的全部程序文本為訓(xùn)練集,將每一個類作為一篇文檔,訓(xùn)練Doc2Vec 模型.通過該模型,可計算任意兩組代碼段文本的余弦相似度.余弦相似度的值域落在[?1,1]間,負(fù)值的物理意義即為負(fù)相關(guān).由于負(fù)值偶發(fā),且本文不關(guān)注代碼段負(fù)相關(guān)的信息,參照Positive PMI[28,29]對類似問題的處理方式,將余弦相似度的負(fù)值視為0,即對于文本段Ta,Tb,其中a與b為任意代碼片段,其相似度定義如式(8)所示.
Fig.4 Overview of textual analysis圖4 文本分析概覽
本文采用類似的方式,利用LDA 計算文本的相似度,并將其作為對照組,相似度值域?yàn)閇0,1].
本文參考Palomba 等人[18]使用系統(tǒng)內(nèi)全部非零度量值的中位數(shù)(non-null median)作為TIfe和TIblob的閾值.
3.2.1 文本方式檢測FE
此方法的基本思路是:對于被檢函數(shù)f,若存在一個非所屬類,它與f的相似度比f同所屬類的相似度相比更高,則存在耦合,可判定檢出FE.定義f所屬的類為CO,計算f所有類的集合SCALL中每個類的文本相似度.即:對于任意Ci∈SCALL,計算PSIM(f,Ci),記錄最大值為MaxPSIM,如式(9)所示.
對于FE,定義Code Smell 的強(qiáng)度[6]為式(10).
3.2.2 結(jié)構(gòu)方式檢測Blob
此方法的基本思路是:類的函數(shù)間越不相關(guān),則類的內(nèi)聚性越低,Blob 的強(qiáng)度越大.
對于被檢類C及其函數(shù)成員的集合F,如式(11)所示,定義Code Smell 的強(qiáng)度[6]為
其中,ClassCohesion 為類函數(shù)間的相關(guān)性計算函數(shù),其定義[15]如式(12)所示.
本文按設(shè)計問題將Code Smell 分為內(nèi)聚類和耦合類,圖5 中的Blob 屬于內(nèi)聚類,圖6 中的DC 和FE 屬于耦合類.
判定分為兩個步驟:首先,篩選Code Smell 度量強(qiáng)度超過閾值的檢測對象;其次,根據(jù)文本和結(jié)構(gòu)方式的強(qiáng)度確定Code Smell 的最終強(qiáng)度.對于Blob,通過結(jié)構(gòu)和文本分析檢測到的Code Smell 之并集識別.如式(13)所示,強(qiáng)度值Iblob取兩者的最大值:
對于DC,本文采用結(jié)構(gòu)分析識別,即NSIdc>動態(tài)閾值,如圖6.強(qiáng)度值Idc取結(jié)構(gòu)分析的強(qiáng)度如式(14)所示.
對于FE,本文將存在結(jié)構(gòu)耦合(0 Fig.5 Unified identification strategy of cohesion design problem圖5 內(nèi)聚設(shè)計問題的綜合判定策略 Fig.6 Unified identification strategy of coupling design problem圖6 耦合設(shè)計問題的綜合判定策略 本文的先進(jìn)性體現(xiàn)在以下幾處:在結(jié)構(gòu)分析方面,本文討論并選定了3 種Code Smell 的檢測方式和閾值,針對JS 檢測任務(wù)提升了DC 檢測涉及的FDP 和CDISP 指標(biāo)的寬容度,使其適應(yīng)類型不明的情況;在文本分析方面,本文使用了更優(yōu)的文本分析算法,并利于文本語義特征實(shí)現(xiàn)文本和結(jié)構(gòu)分析的檢測結(jié)果互補(bǔ).針對兩種分析方法的特點(diǎn),本文制定了3 種Code Smell 的綜合判定策略. 將文本分析和結(jié)構(gòu)分析結(jié)合是可行且有效的. ?一方面,代碼組件的文本中蘊(yùn)含業(yè)務(wù)邏輯和組件功能(例如service,manager)信息,這些信息在結(jié)構(gòu)分析時往往難以被充分利用[30].已有學(xué)者嘗試改善這一情況,例如:Moha 等人[26]檢測Blob 時,在結(jié)構(gòu)方式的基礎(chǔ)上根據(jù)類名判斷組件功能;Palomba 等人[15]通過實(shí)驗(yàn)得出文本和結(jié)構(gòu)分析的檢測結(jié)果互補(bǔ),相互結(jié)合可以獲得更好的檢測效果,將兩種信息源結(jié)合的工作較少. ?另一方面,JavaScript 的類型系統(tǒng)和Java 等強(qiáng)類型語言不同,在變量聲明時無需明確類型,導(dǎo)致傳統(tǒng)的靜態(tài)分析難以奏效,無法獲得像強(qiáng)類型語言一樣詳實(shí)的類型信息. 判定Blob 使用文本和結(jié)構(gòu)方式的最大值的原因是:(1) Blob 的結(jié)構(gòu)方式只需要檢測訪問本地和外部數(shù)據(jù)的次數(shù),對于外部數(shù)據(jù)的訪問,無需明確操作涉及的類,因此獲得的結(jié)構(gòu)信息是完整的;(2) 本文的強(qiáng)度值均標(biāo)準(zhǔn)化至[0,1]區(qū)間,可以直接比對. 判定FE 時,之所以優(yōu)先取文本方法的檢測值,是因?yàn)榻Y(jié)構(gòu)方式檢測FE 需要確定耦合對象所屬的類.由于JS使用弱類型系統(tǒng),變量的類型在分析中僅靠推斷得出,因此這一結(jié)構(gòu)信息可能檢測不全.文本方式根據(jù)語義相似度確定是否耦合,不受此限制,因而更可靠. 判定FE 時,使用CINT 作為閾值的原因?yàn)?一方面,計算CINT 無需確定耦合對象所屬的類,因此該度量的值是可靠的;另一方面,存在業(yè)務(wù)邏輯類似但實(shí)則毫無關(guān)聯(lián)的代碼,它們可能會導(dǎo)致文本方式的誤判,例如將代碼拷貝誤判為耦合,使用CINT 閾值可以應(yīng)對這種情況. 為了驗(yàn)證JS4C 的有效性,本文以表3 中的開源項(xiàng)目作為測試數(shù)據(jù)集,對JS4C 的檢測結(jié)果進(jìn)行評估對比.實(shí)驗(yàn)主要尋求以下幾個問題的解答. Q1:JS4C 能否準(zhǔn)確檢測內(nèi)聚和耦合的設(shè)計問題? Q2:JS4C 有哪些已知問題?是否仍有改進(jìn)空間? Q3:文本檢測算法是否提升了JS4C 的檢測效果? Q4:哪些因素會影響實(shí)驗(yàn)評估結(jié)論的有效性? Q5:如何基于JS4C 給出JavaScript 類的重構(gòu)建議,并實(shí)現(xiàn)其應(yīng)用意義? Table 3 Open source project dataset used for experiment表3 實(shí)驗(yàn)所用開源項(xiàng)目數(shù)據(jù)集 為了保證基礎(chǔ)數(shù)據(jù)的準(zhǔn)確性,實(shí)驗(yàn)首先對基礎(chǔ)度量數(shù)據(jù)進(jìn)行了驗(yàn)證.由于缺乏對比的工具,本節(jié)實(shí)驗(yàn)參照同類Code Smell 的工作[1,3],將對比基準(zhǔn)確定為人工檢測.檢測工作由本文的第一作者及一名擁有3 年工作經(jīng)驗(yàn)的Web 應(yīng)用開發(fā)者分別獨(dú)立進(jìn)行后,針對分歧討論完成. 其中,Doc2Vec 和LDA 的相似度值分別使用Deeplearning4j 和JGibbLDA庫計算,它們被軟件分析相關(guān)研究[31]和開源社區(qū)廣泛驗(yàn)證和使用,因此文本分析的人工驗(yàn)證僅涉及輸入數(shù)據(jù)和運(yùn)算的準(zhǔn)確性.結(jié)構(gòu)方式的度量值均源于抽象語法樹的結(jié)構(gòu)信息,驗(yàn)證工作將人工計算的結(jié)果與工具的結(jié)果進(jìn)行了對比. 獲取可靠的度量值后,實(shí)驗(yàn)需要進(jìn)一步驗(yàn)證JS4C 對實(shí)際內(nèi)聚、耦合設(shè)計問題的檢測效果.本文對數(shù)據(jù)集中的項(xiàng)目采用了與度量值驗(yàn)證相同的人工檢測流程,特別地,對于耦合問題,除了判定有無設(shè)計問題外,還需識別出所有人工判定發(fā)生耦合的對象,否則視為錯判. 為了回答Q1 和Q2,本文使用精確率(precision)和召回率(recall)度量檢測的效果,指標(biāo)的數(shù)值越大,表明檢測的效果越好.將Code Smell 檢測視作一個二分類問題,將存在Code Smell 的類歸為正樣本類,不存在Code Smell的類歸為負(fù)樣本類.令預(yù)測為正的正樣本數(shù)量為TP(true positive,正確率)、預(yù)測為正的負(fù)樣本數(shù)量為FP(false positive,誤報率)、預(yù)測為負(fù)的正樣本數(shù)量為FN(false negative,漏報率),精確率和召回率分別如式(16)、式(17)所示: 本文對數(shù)據(jù)集中全部的項(xiàng)目進(jìn)行了檢測,本節(jié)以Awesome-qr.js 案例和Three.js 為例,說明實(shí)驗(yàn)過程.本節(jié)的度量數(shù)據(jù)在第4.2 節(jié)中的表7~表9 展示. Awesome-qr.js 的1.2.0 版本[32]約有1 500 行代碼,可在客戶端或服務(wù)端運(yùn)行.它擁有兩個工具類、7 個功能類,且多個類具有低內(nèi)聚特征. 表4 列出了對該項(xiàng)目受FE 和DC 影響的全部函數(shù)及檢測結(jié)果.由于上述函數(shù)的代碼及變量命名均無顯著的業(yè)務(wù)特征(例如mod 和multiply)或特征過多、分散(例如draw),甚至未出現(xiàn)在軟件項(xiàng)目中,故文本分析難以確定目標(biāo)的耦合類.然而,它們的確存在耦合問題,對于這類較為困難的任務(wù),JS4C 體現(xiàn)出了良好的適應(yīng)性. Table 4 Detection results and effectiveness of FE and DC in Awesome-qr.js表4 Awesome-qr.js 中FE 和DC 的檢測結(jié)果和檢測效果 表5 列出了該項(xiàng)目Blob 的檢測結(jié)果.在上述檢測結(jié)果中,對于QR8bitByte,文本分析未檢測到Code Smell,而結(jié)構(gòu)分析檢出了最高強(qiáng)度的Code Smell.因?yàn)轭愔卸x了多個未經(jīng)函數(shù)成員訪問的屬性,內(nèi)聚性不足,但函數(shù)成員的名稱卻與業(yè)務(wù)邏輯有關(guān).對于AwesomeQRCode,它未包含任何屬性成員,故結(jié)構(gòu)分析會失效,但文本分析卻可以檢測出它實(shí)現(xiàn)了不相關(guān)的多種職責(zé). Table 5 Detection results and effectiveness of Blob in Awesome-qr.js表5 Awesome-qr.js 中Blob 的檢測結(jié)果和檢測效果 Awesome-qr.js 的體積較小,在相關(guān)性分析中難以獲取足夠的有效數(shù)據(jù),需要使用規(guī)模較大的軟件演示后續(xù)步驟.Three.js[33]是利用WebGL 和HTML5 特性實(shí)現(xiàn)的開源瀏覽器端三維引擎,截至2018 年9 月,該項(xiàng)目已有近25 000 次代碼提交(commit)、88 個發(fā)布(release)版本和近1 000 名代碼貢獻(xiàn)者(contributor).本文利用JS4C 對Three.js r95 版本代碼中的232 個類進(jìn)行了檢測,并分析Code Smell 的分布規(guī)律及它們之間的關(guān)系,其中,共103個類涉及本文討論的3 種Code Smell. 對于系統(tǒng)內(nèi)所有的類,獲取3 種Code Smell(Blob,FE,DC)強(qiáng)度的集合BLOB,FE,DC.本文利用Spearman 等級相關(guān)方法(Spearman’s rank correlation coefficient)[34]分析三者間的兩兩相關(guān)性,該方法可用于未知概率分布的兩組順序數(shù)據(jù),取上述兩組數(shù)據(jù)作為輸入值,可輸出其相關(guān)系數(shù)ρ及相關(guān)性的顯著程度P.判定顯著程度前,需要選定一個顯著等級(significant level)值α,實(shí)踐中,α通常取值0.05[6].在該取值下,當(dāng)P<α?xí)r,可認(rèn)為兩組數(shù)據(jù)的差異具有顯著性,即具有統(tǒng)計意義;當(dāng)P<0.01 時,可認(rèn)為兩組數(shù)據(jù)的差異非常顯著.相關(guān)系數(shù)ρ利用單調(diào)方程評價兩個統(tǒng)計變量的相關(guān)性,它的值域?yàn)閇?1,1].如表6 所示,ρ值可對應(yīng)相關(guān)性,當(dāng)數(shù)據(jù)中沒有重復(fù)值,且兩組變量完全單調(diào)相關(guān)時,ρ相關(guān)系數(shù)則為+1 或?1. Table 6 Spearman’s rank coefficient value ρ and its correlation level表6 Spearman 秩相關(guān)系數(shù)ρ的值及其相關(guān)性 本文對Three.js 的3 種Code Smell 檢測結(jié)果進(jìn)行兩兩分析,得出結(jié)論:FE 和DC 呈現(xiàn)弱強(qiáng)度的負(fù)相關(guān)性,其中ρ為?0.30(P=0.001);BLOB 和FE 呈現(xiàn)中等強(qiáng)度的正相關(guān)性;BLOB 和DC 的差異不具統(tǒng)計意義. 本文進(jìn)一步探究耦合設(shè)計問題和內(nèi)聚設(shè)計問題的關(guān)系. 將Code Smell 分為兩類,令內(nèi)聚Code Smell(Blob)為一類,令耦合Code Smell(FE,DC)為另一類.類低內(nèi)聚的強(qiáng)度ILC取類的Iblob.一個類具有多個函數(shù),因而具有多個FE 與DC 強(qiáng)度值,對于耦合Code Smell,本文取其均值mean(Ife),mean(Idc),類高耦合IHC的強(qiáng)度優(yōu)先考慮同一個類發(fā)生耦合,即取mean(Ife),若mean(Ife)≤0,則取mean(Idc).對于系統(tǒng)內(nèi)所有的類,可以獲得低內(nèi)聚強(qiáng)度的集合LC和高耦合強(qiáng)度的集合HC. 本文利用Spearman 秩相關(guān)系數(shù)分析LC和HC的相關(guān)性,僅考慮IHC,ILC均大于0 的情況,得到P值遠(yuǎn)小于0.05(6.3e?18),ρ為0.46.實(shí)驗(yàn)發(fā)現(xiàn),該項(xiàng)目耦合和內(nèi)聚的強(qiáng)度具有弱正相關(guān)性. 將低內(nèi)聚、高耦合類交集的元素個數(shù)與低內(nèi)聚、高耦合類并集的元素個數(shù)的比值作為同現(xiàn)率,得出同現(xiàn)率為66.88%.本文進(jìn)一步使用Wilcoxon 秩和檢驗(yàn)(Wilcoxon rank-sum test)[35]分析兩組數(shù)據(jù)的總體分布是否差異顯著:若差異不顯著,則相關(guān)性和同現(xiàn)率無實(shí)際意義.秩和檢驗(yàn)亦輸出顯著程度P,顯著等級取值和α相同.分析得出,LC和HC的分布顯著不同(P=6.27e?34). 通過與第4.1 節(jié)類似的方式,本文對數(shù)據(jù)集中的所有項(xiàng)目進(jìn)行了檢測,檢測結(jié)果在表7~表9 中列出.在表7和表8 中,為了驗(yàn)證文本方式對結(jié)果的貢獻(xiàn),實(shí)驗(yàn)單獨(dú)列出了去除文本方式后的數(shù)據(jù)(即“純結(jié)構(gòu)”列).“重合度”為使用Doc2Vec 和LDA 作為文本算法的檢測結(jié)果中重復(fù)的部分(交集)占全部檢測結(jié)果(并集)的比重;“非重合部分占比”為去除重復(fù)部分的全部檢測結(jié)果中,二者檢測出的信息分別所占的比重. Table 7 Detection results of coupling design problems (%)表7 耦合設(shè)計問題的檢測結(jié)果 (%) Table 8 Detection results of cohesion design problems (%)表8 內(nèi)聚設(shè)計問題的檢測結(jié)果 (%) Table 9 Other detection results (%)表9 其他檢測結(jié)果 (%) 對于Q1,根據(jù)表7 和表8 中Doc2Vec 列的精確率和召回率數(shù)據(jù),可見其總體表現(xiàn)與檢測Java Code Smell的同類文獻(xiàn)[15]相仿,JS4C 能夠比較準(zhǔn)確地檢測和識別內(nèi)聚和耦合問題.如表7 所示,使用Doc2Vec 作為文本檢測算法的JS4C 在檢測耦合問題方面的整體表現(xiàn)更好,在保持與其他方式相當(dāng)精確率的前提下,大幅提升了召回率;如表8 所示,在檢測內(nèi)聚問題時,其優(yōu)勢更為全面和顯著. 本文還參考相關(guān)文獻(xiàn)得出的內(nèi)聚和耦合問題的關(guān)聯(lián)和性質(zhì),通過表9 中第4 列、第5 列的其他指標(biāo)驗(yàn)證了其中的結(jié)論,以印證對Q1 的回答.Badri 等人[36]指出,內(nèi)聚和耦合的度量間存在相關(guān)性.數(shù)據(jù)集的6 個項(xiàng)目中,有4個得出了類似結(jié)論,其中,Awesome-qr.js 相關(guān)性不顯著的原因是數(shù)據(jù)不足.Chahal 等人[8]認(rèn)為:“高內(nèi)聚、低耦合”盡管在設(shè)計原則中并列出現(xiàn),但實(shí)現(xiàn)高內(nèi)聚不意味著低耦合,然而在復(fù)用性較差的設(shè)計中,二者會同時出現(xiàn).根據(jù)秩和檢驗(yàn)P值,可知內(nèi)聚和耦合問題的分布顯著不同,因此它們并不是同一種問題;通過同現(xiàn)率,可印證兩種問題有較高概率同時出現(xiàn). 對于Q2,JS4C 包含因上游軟件和算法等特性較難排除的已知問題,以及針對軟件的具體情況而排除的干擾因素,排除干擾因素可以有針對性地提升在特定項(xiàng)目中的表現(xiàn),已知問題則需要在后續(xù)工作中持續(xù)改進(jìn). 已知問題包括:(1) JS4C 基于類檢測工具JSDeodorant 擴(kuò)展,檢測效果受其制約,盡管JSDeodorant 是目前效果最好的JS 類檢測工具,但由于實(shí)現(xiàn)類的方式多樣,工具會漏檢部分構(gòu)造不規(guī)范的類(例如使用對象定義且沒有構(gòu)造器的情形),影響到了檢測精度;(2) 文本過短會導(dǎo)致文本模型得出不合理的相似度,因此目前有較多代碼行數(shù)較小的類被誤判為低內(nèi)聚類;(3) 由于JS 使用弱類型系統(tǒng),目前使用被調(diào)用函數(shù)簽名的特征推斷對象的類,如果特征不明顯,對象所屬的類可能無法被準(zhǔn)確推斷,進(jìn)而影響NSCDISP,ATFM 等結(jié)構(gòu)方式度量計算. 除此之外,還有能因地制宜而排除的干擾因素. 在檢測耦合問題的實(shí)驗(yàn)中,JS4C 在Three.js 和FloraJS 的例子中的精確率表現(xiàn)不甚理想,主要的錯判包括2類情況. (1) 與瀏覽器支持的WebGL、Canvas 和頁面事件等功能接口交互的類和函數(shù)中,JS4C 的結(jié)構(gòu)方式將其識別為一種不明來源的耦合,它們實(shí)為對瀏覽器底層功能的封裝.對于這類問題,可以通過建立瀏覽器底層功能函數(shù)庫的白名單,并將這些函數(shù)列入文本檢測流程中的“停用詞”范疇,以優(yōu)化檢測效果. (2) 由于文本相似度檢測的特性,FE 的檢測會受到Duplicate Code(重復(fù)代碼)的干擾.在Code Smell 優(yōu)先級排序的相關(guān)研究中[37],Duplicate Code 優(yōu)先于FE,該問題可通過Code Smell 排序的方式規(guī)避. 在檢測內(nèi)聚問題的實(shí)驗(yàn)中,受干擾導(dǎo)致的錯判包括3 類情況. (1) 數(shù)據(jù)類(data class)或模型類(model)中與業(yè)務(wù)邏輯無關(guān)的存取和序列化等函數(shù)提高了結(jié)構(gòu)方式內(nèi)聚性的度量值、干擾了判斷:一方面,JS 的存取函數(shù)并沒有通用的模板代碼,其命名和實(shí)現(xiàn)方式不遵循特定規(guī)則;另一方面,部分存取函數(shù)也包含少量的業(yè)務(wù)邏輯,因此不能簡單地排除全部的存取函數(shù). (2) 代碼中存在大篇幅的、與業(yè)務(wù)邏輯無關(guān)的變量默認(rèn)值,影響了文本方式的判斷結(jié)果. (3) 部分工具類有低內(nèi)聚的特性,易被判為低內(nèi)聚類.對于該問題,一方面,工具類是否為反模式仍有爭論;另一方面,若實(shí)有必要,可以通過工具函數(shù)的檢測算法[38]將其排除. 對于Q3,文本檢測算法提升了檢測效果:一方面,在表9 中,易見文本信息源占據(jù)了約4 成的比例,是重要的信息源;另一方面,文本方式檢測出了更多的、有效的信息.根據(jù)表7 和表8 中Doc2Vec 和純結(jié)構(gòu)方式的對比,易見前者使召回率有普遍提升,即檢測到了更多的設(shè)計問題;Doc2Vec 檢測出的額外信息沒有對精確率造成嚴(yán)重影響,在內(nèi)聚問題的檢測中還使精確率有顯著提升,即檢測到了有效的信息. 在文本方式的算法中,Doc2Vec 方法的整體優(yōu)于LDA.從表7 和表8 中的“重合度”可以看出,兩種文本算法的檢測結(jié)果具有一定相似性;但從“非重合部分占比”數(shù)據(jù)可以看出,在余下的不重合部分,Doc2Vec 方法普遍比LDA 能檢測出更多不同的數(shù)據(jù).根據(jù)Q1 的結(jié)論,可見這些數(shù)據(jù)顯著提升了檢測效果.因此,Doc2Vec 更適合作為本文的文本分析檢測算法. 對于Q4,本文實(shí)驗(yàn)評估的有效性威脅包括以下3 點(diǎn). (1) 數(shù)據(jù)集項(xiàng)目的選取問題.本文從GitHub 和JS 類檢測的文獻(xiàn)[7]中選取了運(yùn)行環(huán)境多樣、功能不同且將類作為主要設(shè)計模式的JS 項(xiàng)目用于驗(yàn)證實(shí)驗(yàn)結(jié)果,但僅涉及了6 個開源項(xiàng)目,無法涵蓋JS 程序的全部應(yīng)用領(lǐng)域. (2) 人工標(biāo)注設(shè)計問題的主觀因素.由于缺乏可供參照的同類工作和數(shù)據(jù)集,因此用于驗(yàn)證有效性的設(shè)計問題是人工標(biāo)注的,存在主觀因素.因此,本文參考其他學(xué)者[3]的做法,引入具備JS 開源項(xiàng)目經(jīng)驗(yàn)的開發(fā)者合作標(biāo)注問題,以期還原現(xiàn)實(shí)的軟件開發(fā)和維護(hù)情境. (3) 動態(tài)閾值的選取問題.由于缺乏JS 類度量指標(biāo)的統(tǒng)計數(shù)據(jù),為了保障檢測方法的適應(yīng)性,本文不使用固定閾值檢測.對于Java Code Smell 的文獻(xiàn)中采用固定閾值的度量(例如結(jié)構(gòu)方式的DC 和FE),本文根據(jù)閾值得出的方式針對每個項(xiàng)目分別統(tǒng)計,形成動態(tài)閾值.對于這類改為動態(tài)閾值的度量,圖7 展示了全部數(shù)據(jù)集類中它們原始數(shù)值的分布,并用分別標(biāo)注出了原始文獻(xiàn)中的固定值(虛線)和統(tǒng)計數(shù)據(jù)集得出的值(實(shí)線).根據(jù)兩者差值的絕對值同固定值的比值計算,可以得出不同度量的動態(tài)閾值與固定閾值有5%(LCOM5)~20%(CINT)不等的差異. Fig.7 Distributions and thresholds of 3 metrics圖7 3 種度量的分布及閾值 對于Q5,JS4C 可以量化代碼異味強(qiáng)度,通過提升JS 類的內(nèi)聚、降低耦合來消除強(qiáng)度高的代碼異味,進(jìn)而實(shí)現(xiàn)高效的JS 類重構(gòu).然而,近期有研究指出:除了異味強(qiáng)度外,還有代碼的運(yùn)行環(huán)境、模塊和組件的重要程度等情境因素影響代碼異味的重構(gòu)優(yōu)先級[39],在特殊的情境下,代碼異味可能不構(gòu)成軟件設(shè)計問題.因此,在實(shí)際應(yīng)用場景中,未被納入考慮的情境因素可能降低代碼異味強(qiáng)度的參考價值.這一問題可以通過實(shí)現(xiàn)情境感知的代碼優(yōu)先級排序來解決,它綜合考慮影響代碼質(zhì)量和重構(gòu)優(yōu)先級的多方面因素,代碼異味強(qiáng)度是其中的一維特征[39]. JS 已成為最常用的編程語言之一,然而在JS 項(xiàng)目中,仍未充分實(shí)現(xiàn)常見類Code Smell 的檢測.本文針對DC、FE 和Blob 這3 種Code Smell,結(jié)合文本分析和代碼結(jié)構(gòu)靜態(tài)分析,提出了一個檢測JS 類的內(nèi)聚耦合Code Smell的方法JS4C,并在實(shí)驗(yàn)部分,通過對6 個開源項(xiàng)目的分析,證明了JS4C 對內(nèi)聚和耦合的設(shè)計問題有良好的檢測效果. 后續(xù)工作有3 個方向:其一,研究的范圍可以拓展到基于瀏覽器端框架的業(yè)務(wù)代碼,檢測與框架設(shè)計相關(guān)的內(nèi)聚耦合Code Smell;其二,對大量的工業(yè)軟件項(xiàng)目進(jìn)行大樣本的檢測,進(jìn)一步提高檢測工具的穩(wěn)定性和表現(xiàn),并對Code Smell 及耦合、內(nèi)聚問題進(jìn)行詳細(xì)的質(zhì)性分析;其三,可以將結(jié)構(gòu)檢測和文本檢測的結(jié)合方法進(jìn)一步改進(jìn),近期出現(xiàn)了基于深度學(xué)習(xí)模型、抽象語法樹中的名稱和結(jié)構(gòu)特征及詞向量分析代碼功能的方法[40],其對Code Smell 檢測的幫助也是值得研究的.3.4 可行性分析
4 實(shí) 驗(yàn)
4.1 實(shí)驗(yàn)過程
4.2 實(shí)驗(yàn)結(jié)果
4.3 實(shí)驗(yàn)討論
4.4 有效性威脅
5 結(jié)論和后續(xù)工作