圈復(fù)雜度(Cyclomatic complexity)也稱為條件復(fù)雜度或循環(huán)復(fù)雜度桥爽,是一種軟件度量肥矢,是由Thomas J. McCabe, Sr. 在 1976 年提出哈垢,用來表示程序的復(fù)雜度忠烛,其符號(hào)為 VG 或是 M概耻。圈復(fù)雜度是對(duì)源代碼中線性獨(dú)立路徑數(shù)的定量測量芥喇。
圈復(fù)雜度使用的程序的控制流圖來計(jì)算:在圖中的節(jié)點(diǎn)對(duì)應(yīng)于程序中一組不可分割的命令[代碼行]西采,有向邊連接兩個(gè)可連續(xù)執(zhí)行的節(jié)點(diǎn);[可連續(xù)執(zhí)行的兩個(gè)節(jié)點(diǎn):第二個(gè)節(jié)點(diǎn)的命令組可能在第一個(gè)節(jié)點(diǎn)執(zhí)行后立刻開始執(zhí)行]继控。圈復(fù)雜度可以應(yīng)用到獨(dú)立的功能械馆,模塊,方法或類武通。
基礎(chǔ)路徑測試:通過測試用例測試程序中的每個(gè)線性無關(guān)的獨(dú)立路徑霹崎;在這種測試策略下,測試用例的數(shù)目將等于該程序的圈復(fù)雜度冶忱;
圈復(fù)雜度定義
圈復(fù)雜度度量的是程序中線性獨(dú)立路徑的數(shù)量尾菇;例如:如果程序中不包含控制、判斷囚枪、條件語句(例如 if派诬,swith 等),那么復(fù)雜度就是 1 链沼;因?yàn)檎麄€(gè)程序只有一條執(zhí)行路徑默赂;如果程序包含一條IF語句,那么就會(huì)有兩條路徑來執(zhí)行完整個(gè)程序(IF為 TRUE括勺,IF 為 FALSE)放可,所以這時(shí)候的復(fù)雜度就是 2;兩個(gè)嵌套的 IF 語句朝刊,或者包含兩個(gè)判斷條件的一個(gè) IF 語句耀里,復(fù)雜度就是 4;
在數(shù)學(xué)上拾氓,一個(gè)結(jié)構(gòu)化程序的圈復(fù)雜度通過該程序的控制流圖來定義冯挎;控制流圖包含程序的基本塊(圖的節(jié)點(diǎn)),和兩個(gè)基本塊之間可執(zhí)行性(圖的邊)。
原理:
上圖:單程序的控制流圖房官。此程序由紅色的節(jié)點(diǎn)開始運(yùn)行趾徽,然后進(jìn)入循環(huán)(紅色節(jié)點(diǎn)下由三個(gè)節(jié)點(diǎn)組成),離開循環(huán)后有條件分支翰守,最后運(yùn)行藍(lán)色節(jié)點(diǎn)后結(jié)束孵奶,此控制流圖中,E = 9, N = 8, P = 1蜡峰,因此其圈復(fù)雜度為 9 - 8 + (2*1) = 3
數(shù)學(xué)表達(dá)式:
M = E - N + 2P
其中
E 為圖中邊的個(gè)數(shù)
N 為圖中節(jié)點(diǎn)的個(gè)數(shù)
P 為連接組件的個(gè)數(shù)
強(qiáng)連通圖的圈復(fù)雜度定義:要求做完線上功能的先要求線上的功能
上圖:對(duì)應(yīng)同一個(gè)程序的控制流圖了袁,但多加一個(gè)從結(jié)束點(diǎn)到啟始點(diǎn)的邊,因此為強(qiáng)連通的控制流圖湿颅,若利用此圖計(jì)算圈復(fù)雜度载绿,其公式為 M=E-N+P,而 E = 10油航、N = 8崭庸、P = 1,因此圈復(fù)雜度為 3
另一個(gè)計(jì)算圈復(fù)雜度的公式用與計(jì)算每一個(gè)結(jié)束節(jié)點(diǎn)總是連接到啟動(dòng)節(jié)點(diǎn)的流程控制圖谊囚;這種圖稱為強(qiáng)連通的怕享;此時(shí)的圈復(fù)雜度就是圖中回路的個(gè)數(shù),也稱為第一貝蒂數(shù)[first Betti number])镰踏,其公式如下:
M = E - N + P
上式可以視為計(jì)算圖中線性獨(dú)立回路(回路內(nèi)不包括其他回路)的個(gè)數(shù)熬粗,由于控制流圖增加結(jié)束點(diǎn)到啟始點(diǎn)的邊,因此對(duì)應(yīng)一個(gè)結(jié)束點(diǎn)至少會(huì)有一個(gè)回路余境。
對(duì)于單一的程序(或副程序或方法),P 恒為 1灌诅。對(duì)于單一子程序芳来,該公式可以簡單的表達(dá)為:
M = E - N + 2
圈復(fù)雜度可以適用于同時(shí)分析許多程序或副程序的情形(例如針對(duì)一個(gè)類中的所有方法),此時(shí) P 等于程序的個(gè)數(shù)猜拾,因?yàn)槊恳粋€(gè)程序的圖都是一個(gè)獨(dú)立的連接組件即舌。若每一個(gè)程序都只一個(gè)結(jié)束點(diǎn),P 也可以視為是結(jié)束點(diǎn)的個(gè)數(shù)挎袜。
McCache 證明了任何只有一個(gè)進(jìn)入點(diǎn)和一個(gè)技術(shù)點(diǎn)的結(jié)構(gòu)化程序顽聂,其圈復(fù)雜度等于程序中決策點(diǎn)(IF,F(xiàn)OR loops)的個(gè)數(shù)加 1盯仪;
圈復(fù)雜度也可以延伸到多個(gè)結(jié)束點(diǎn)的程序紊搪,此時(shí)的圈復(fù)雜度如下:
π - s + 2
其中
π 是程序中決策點(diǎn)的個(gè)數(shù)
s 為結(jié)束點(diǎn)的個(gè)數(shù)
圈復(fù)雜度應(yīng)用
限制軟件復(fù)雜度
麥凱布提出圈復(fù)雜度時(shí),其原始目的之一就是希望在軟件開發(fā)過程中就限制其復(fù)雜度全景。他建議程序設(shè)計(jì)者需計(jì)算其開發(fā)模塊的復(fù)雜度耀石,若一模塊的圈復(fù)雜度超過 10,需再分區(qū)為更小的模塊爸黄。NIST(國家標(biāo)準(zhǔn)技術(shù)研究所)的結(jié)構(gòu)化測試方法論已此作法略作調(diào)整滞伟,在一些特定情形下揭鳞,模塊圈復(fù)雜度上限放寬到 15 會(huì)比較合適。此方法論也承認(rèn)有些特殊情形下梆奈,模塊的復(fù)雜度需要超過上述的上限野崇,其建議為“模塊的圈復(fù)雜度需在上限范圍以內(nèi),否則需提供書面數(shù)據(jù)亩钟,說明為何此模塊圈復(fù)雜度有必要超過上限乓梨。”
評(píng)估軟件的結(jié)構(gòu)化程度 「structuredness」
Essential complexity (numerical measure of "structuredness")
啟示軟件測試工作
圈復(fù)雜度決定了需要多少個(gè)測試用來達(dá)到特定模塊測試覆蓋率要求径荔;
模塊內(nèi)聚性的評(píng)估
可以預(yù)期一個(gè)復(fù)雜度較高模塊的內(nèi)聚性會(huì)比較低督禽,至少不會(huì)到功能內(nèi)聚性的程度。一個(gè)有高復(fù)雜度及低內(nèi)聚性的模塊中會(huì)有許多的決策點(diǎn)总处,這類的模塊多半運(yùn)行超過一個(gè)明確定義的任務(wù)狈惫,因此內(nèi)聚性較低。一個(gè) 2005 年的研究發(fā)現(xiàn)復(fù)雜度的度量和由專家評(píng)估的模塊內(nèi)聚性有高度負(fù)相關(guān)鹦马,反而針對(duì)內(nèi)聚性設(shè)計(jì)的度量和專家評(píng)估結(jié)果之間的相關(guān)性還比較不明顯[6]胧谈。
推測軟件缺陷個(gè)數(shù)
許多研究指出一模塊及方法的圈復(fù)雜度和其中的缺陷個(gè)數(shù)有相關(guān)性,許多這類研究發(fā)現(xiàn)圈復(fù)雜度和缺陷個(gè)數(shù)有高度的正相關(guān):圈復(fù)雜度最高的模塊及方法荸频,其中的缺陷個(gè)數(shù)也最多菱肖。
不過,有些研究是在控制模塊大小相近的情形下進(jìn)行分析(例如比較二個(gè)源代碼行數(shù)相近旭从,但圈復(fù)雜度不同模塊的缺陷個(gè)數(shù))稳强,許多這類的研究發(fā)現(xiàn)圈復(fù)雜度和缺陷個(gè)數(shù)沒有明顯相關(guān),不過仍有一些研究認(rèn)為在此情形下二者仍有相關(guān)性和悦。有些此領(lǐng)域的研究者認(rèn)為那些研究結(jié)果圈復(fù)雜度和缺陷個(gè)數(shù)沒有明顯相關(guān)的研究退疫,其研究方法的有效性可能有問題。
萊斯·哈頓認(rèn)為利用圈復(fù)雜度來預(yù)測缺陷個(gè)數(shù)鸽素,和利用源代碼行數(shù)來預(yù)測缺陷個(gè)數(shù)的結(jié)果大致相近褒繁。
OneAPM Mobile Insight 以真實(shí)用戶體驗(yàn)為度量標(biāo)準(zhǔn)進(jìn)行 Crash 分析,監(jiān)控網(wǎng)絡(luò)請(qǐng)求及網(wǎng)絡(luò)錯(cuò)誤馍忽,提升用戶留存棒坏。訪問 OneAPM 官方網(wǎng)站感受更多應(yīng)用性能優(yōu)化體驗(yàn),想閱讀更多技術(shù)文章遭笋,請(qǐng)?jiān)L問 OneAPM 官方技術(shù)博客坝冕。
本文轉(zhuǎn)自 OneAPM 官方博客