歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~前端
本文來自雲+社區專欄,做者騰訊移動品質中心TMQjava
提到「質量」二字時,咱們的第一反應每每是「有多少BUG?」「性能好很差?「這樣的問題。咱們對軟件產品或服務的質量定義看其能不能知足用戶的需求,包括功能、性能和體驗等維度的指標,咱們能夠經過各類類型的檢測手段來給出其質量高低的度量。可是,若是直接拿出一段源代碼放在咱們面前,問這段代碼的質量好壞時,咱們又該如何做答呢?安全
有人說:「好的代碼就像好的笑話同樣,它不須要解釋(Good code is like a good joke: It needs no explanation)」。有編碼經驗的人對代碼都有必定的「鑑賞力」,能憑感受給出代碼好壞的主觀評價,看到所謂的「意大利麪條式代碼」都會感到不舒服,可是這樣憑感受的方式太個性化、太隨意了,有沒有一種公認的標準來鑑定代碼質量呢?微信
Bob大叔在其著做《代碼整潔之道》的前言中引用了這樣一幅漫畫:架構
使用漫畫中的「每分鐘爆粗數量」來衡量代碼質量是個頗有趣的玩笑,強調了代碼的可讀易懂等這樣的「內在」質量屬性。相對於知足需求規範這樣的「外在」質量屬性,「內在」的代碼質量屬性強調的是支持實現功能需求的代碼內部結構的質量。《Sonar code quality testing essential》一書中從七個維度定義了代碼的這種內在質量,Sonar開發團隊上綱上線的戲稱爲開發人員七宗罪:前端性能
Martin Fowler在其著做《重構:改善即有代碼的設計》中生動形象的使用「代碼壞味道(Bad Code Smells)」來比喻低質量的代碼設計和實現所顯現的「症狀」。書中羅列了22種代碼壞味道以及對應的重構手法。工具
參照這些資料,如今咱們能夠用可測性,可讀性,可理解性,容變性等代碼可維護性維度的質量屬性來衡量代碼質量。代碼質量指的是代碼內在的非功能性的質量,用戶不能直接體驗到這種質量的好壞,代碼質量很差,最直接的「受害者」是開發者或組織自身,由於代碼質量好壞直接決定了軟件的可維護性成本的高低,例如重複代碼會形成維護成本的成倍增長;不規範的代碼、不良註釋和複雜度太高的代碼會增長閱讀和理解代碼的難度,複雜度太高也會極大增長測試覆蓋的難度,耗費過多人力,而缺乏測試覆蓋的代碼會使得定位問題和修復問題的難度加大;結構不良、低內聚高耦合的代碼則會使得哪怕是微小的需求變動或功能擴展都無從下手,修改的代價極可能超過了重寫的代價。性能
至此,咱們獲得了一些定性的辦法來衡量代碼的質量,咱們能夠藉助一些代碼掃描工具來暴露代碼的質量問題,也有了相應的重構方法和技巧來應對這些問題。可是,咱們仍是難以回答某段代碼有多好或多差,兩段代碼相比哪一個更好這樣的問題,由於咱們仍然沒有徹底解決代碼質量的量化問題:一樣都是代碼質量問題,重複代碼和過多註釋的危害確定是不同的;一樣都是方法太複雜,圈複雜度爲10的方法和圈複雜度爲20的方法相比,危害和修改難度也差異很大。因此咱們不能直接用問題的數量來衡量質量,須要找到更精細合理的量化度量方法。單元測試
如何評估軟件產品源代碼質量一直是業界的一大挑戰,SQALE(Software Quality Assessment based on Lifecycle Expectations)方法的出現提供一套科學的度量和分析方法,有效應對了這一挑戰。SQALE方法整合了ISO-25010標準與代碼規範,其目標是:以客觀、準確、可複製和自動化的方式爲評估軟件應用程序的源代碼提供支持;爲管理技術債務提供一種有效的方法。SQALE是目前衆多主流代碼分析工具的參照標準,包括咱們熟知的SonarQube,和CoderGears, SQUORE等商用代碼掃描分析工具。測試
下面咱們簡單介紹一下SQALE方法的原理。SQALE方法包含兩種模型:質量模型和分析模型。下圖的樹型結構展現了SQALE方法的質量模型:樹根節點表明軟件質量(此處即代碼質量),從左向右展開,第一級定義了代碼質量的特徵分類,往下是每種特徵的子類,最後是每一個子類對應的屬性/具體的度量項。
從左向右的方向是把代碼質量不斷細化分解爲更小的單元,直到最小粒度能夠直接度量的屬性;從右向左的方向是把度量值逐步彙總到根節點,最終獲得一個總的代碼質量的度量值。表1是SQALE質量模型分解的示例。表中第一列把代碼質量細分爲可維護性、可測性、可變動性和可靠性幾個維度,對於每一個維度又有進一步的細節,如可測性又細分爲單元測試可測性和集成級可測性這樣的子特徵,進一步的,子特徵還能細化到可直接度量的屬性,或者稱爲要求(表中第三列,即咱們一般說的代碼掃描規則),例如單元測試可測性再細分爲「模塊測試路徑數量<11」和「模塊調用參數數量<6」這樣的規則:
注:咱們使用的SonarQube並無徹底照般SQALE的質量模型,在5.4及以前的版本中還存在與SQALE相似的可測性、易變動性、可理解性和可讀性等維度,整個模型只有兩級,即第一列和第二列合併了,例如可測性維度下直接對應了「表達式不該該太複雜」,「方法不該該太複雜」,「方法不該該有太多參數」等規則。在5.4以後的版本,即目前使用的版本則進一步簡化,代碼質量對應的掃描規則直接歸屬於「壞味道」大類,具體的規則能夠打上多種標籤來歸類,分類和配置更加靈活。
那麼,這些規則應該怎麼量化呢?或者說,如何度量代碼違背規則的程度,並且這種度量是能夠加總的,畢竟規則間差別很大,上文也解釋過,直接按數量彙總確定是不合理的。
怎麼辦呢?SQALE方法的分析模型解決了這個問題,由此咱們也引出了本文中的第二個重要概念:技術債TechnicalDebts。
「技術債」這一律念最先出如今1992年,其本義是指,開發人員爲了加速軟件開發,在應該採用最佳方案時進行了妥協,改用了短時間內能加速軟件開發的方案,從而在將來給本身帶來的額外開發負擔。這個定義暗示了這種「負債」是一種刻意的、理性的通過權衡的行爲,後文中咱們進一步探討技術債務的類型時會指出這必定義僅僅表明了技術債中相對良性的一類,是一個比較「溫和」的定義。此處咱們關注的重點是使用技術債這一隱喻來幫助你們理解度量代碼質量的方法。
既然談的是「債」,天然就應該和錢有關了。所以,技術債的「本金」就定義爲修復代碼質量問題所需消耗人力資源估值,例如,針對java語言,修復一個圈複雜度爲15的方法須要一個開發人員15分鐘的時間(以sonar java分析器缺省設置爲例),這個值就是負債的本金。代碼掃描工具中對應代碼質量的每條掃描規則都對應着一個債務計算方法,有的規則是設定了固定的債務值,有的則根據違規程度有相應的計算公式。引入技術債的概念後,SQALE方法就能夠把不一樣規則對應的代碼質量度量統一爲人力資源的消耗這一單一指標上。
根據圖2質量模型所示由右向左的方向逐級彙總,就能夠獲得待評價軟件的代碼質量度量值。咱們的其中一個度量難題:如何客觀評價代碼的質量,由此就獲得瞭解答。
關於技術債另外還有一個概念值得在這兒強調一下,即負債的利息。咱們知道,一般借錢是有利息的,有的負債利息很低(如安居計劃利息爲0),有的利息較高(如信用卡欠款),有的則高到使人絕望(如高利貸)。一樣,技術債也是有利息的,存在利滾利的狀況,有的違規項立刻修復要10分鐘,若是放着無論一段時間後,也許就須要20分鐘甚至更多的時間來修復(因爲代碼細節的知識隨時間流逝,以及破窗效應形成代碼問題加速惡化等緣由)。有的代碼掃描工具會針對規則定義本金和利息的計算方法,如Coder Gears的CppDepend,咱們目前使用的SonarQube平臺上的代碼掃描插件不支持計算利息,所以本文就不過多討論,你們只須要記住,由於利息的存在,技術債務不及時償還的話,會在將來呈現出非線性增加,形成始料不及的損失。後續文章在討論技術債的危害時,咱們還會時常說起技術債的非線性特徵。
如今咱們還剩下一個度量問題:如何知道兩段代碼的質量差別?如今有了技術債本金這個絕對值,可是不一樣規模,不一樣類型的代碼應該如何比較呢?SQALE方法中繼續借鑑了「負債率」這個術語,計算公式爲:償還債務所需耗費的資源(即本金)除以重寫全部代碼的預估耗費的資源。在掃描工具的實現中,分母是經過代碼量和開發生產力水平計算得出,其中的生產力是一個配置項,如SonarQube上能夠配置編寫一行代碼的平均估計耗時。SQALE進一步使用了術語「債務等級」,定義了從A(很是好)到E(很是差)五個等級,根據負債率數值所在區間對應不一樣的等級,例如SonarQube中缺省[0, 5%]是A,(5%, 10%]是B,(10%,20%]是C,(20%, 50%]是D,高於50%是E。當負債率達到100%時,即債務開始超過資產,資不抵債,這時就稱這種狀況爲「技術破產」。固然,平常工做中碰到這種狀況時,咱們不會用這麼嚇人的術語,一般是打着「重構」的旗號重寫一遍。
下圖是CppDepend的一個掃描彙總結果的示例,包含了咱們討論的全部概念(使用CppDepend爲例是爲了展現更全面的信息)。
上圖中工具掃描的代碼行數爲19862行,共負債32天,債務的年息是9天2小時,負債率是6.39%,債務等級是B級。
咱們平常工做使用的工具平臺是SonarQube,以下圖所示:
圖中的項目負債12天,共有923個壞味道(即違規項數量),負債率(圖中翻譯爲「技術債務比率」)爲6.3%,債務等級(圖中爲SQALE評級)爲B級。
SQALE給咱們提供一套有效合理衡量代碼質量的方法和工具,下圖中SQALE方法流程清晰的展現了整個方法流程各個環節:
圖片來源:http://www.sqale.org
有了方法和工具(SonarQube)的支持,咱們能夠看看咱們本身的代碼質量是個什麼情況。從掃描結果來看,與一些優秀的開源項目相比,咱們仍是有一些差距。部門EP(Engineering Productivity)極社根據掃描結果,挑選出了比較重要的如下4條規則:
Source files should nothave any duplicated blocks,
Classes should not becoupled to too many other classes,
Methods should not be toocomplex,
Control flow statements"if", "for", "while", "switch" and"try" should not be nested too deeply.
注:SonarQube中有些語言對應的掃描插件不支持第2條規則,如C++和Python。
這4條規是咱們須要優先償還的技術債,目前已經在整個部門推廣實施。
讀到這裏,不少人也許忍不住想問,如此這般折騰有啥用?代碼質量相對不高也沒有影響到公司業務呀,提升這種代碼質量除了讓咱們忙上加忙外,能有什麼好處?或者說有什麼價值?跟個人KPI有啥關係?
好吧,既然代碼質量很差就是「負債」,那麼欠債還錢不就是天經地義麼,畢竟「出來混,早晚要還的。」顯然這樣的蒼白說教沒法服衆,因此咱們後續文章的重點就是深刻理解技術債,深刻分析提高代碼質量的必要性和緊迫性。
So:讀者朋友們,大家所在的團隊或組織是否也在重視代碼質量呢?
問答
相關閱讀
此文已由做者受權騰訊雲+社區發佈,原文連接:https://cloud.tencent.com/developer/article/1151495?fromSource=waitui
歡迎你們前往騰訊雲+社區或關注雲加社區微信公衆號(QcloudCommunity),第一時間獲取更多海量技術實踐乾貨哦~