- DevOps落地與轉型:提升研發效能的方法與實踐
- 蔣星辰
- 6713字
- 2023-03-30 22:36:39
1.4 如何可視化管理代碼質量
項目啟動后,接下來的緊張氣氛來到了我們效能團隊這里。我從其他團隊臨時拉了兩個研發人員來配合工作,這也是效能團隊的初創成員。
技術債務又稱技術債,是編程及軟件工程中的一個比喻,指開發人員為了加速軟件開發,在應該采用最佳方案時進行了妥協,改用短期內能加速軟件開發的方案。不過,許多我們歸咎于技術債務的事情實際上根本不是債務。例如,隨著系統使用年限增加,團隊無法一直保持最佳的編碼實踐,在這種情況下團隊增加額外工作量是正常的,不是債務。
首先,我們的第一件大事就是量化每個團隊的技術債務。
1.4.1 靜態代碼質量量化指標
SQALE(Software Quality Assessment based on Lifecycle Expectation,基于生命周期期望的軟件質量評估)是一種支持軟件應用程序源代碼(靜態代碼)評估的方法。它是一種通用方法,獨立于語言和源代碼分析工具。
研發人員肯定都知道SonarQube(簡稱Sonar)平臺。該平臺就是基于SQALE方法,通過設置代碼規則和指標統計來分析和評估代碼質量的,并能夠量化項目技術債務。
我們使用的是Sonar社區版本,其中很多功能受限,比如不支持多分支掃描、無法配置新增指標計算的開始時間等。這些功能實現網上都有一定的替代方案,這里不再詳細講述。
關于指標計算和代碼質量等級劃分,這些是一線研發人員最愛鉆牛角尖的地方,所以我們必須要先搞明白。
1.代碼質量規則配置
通過Sonar平臺,我們可針對不同編程語言設置代碼質量規則,并對代碼質量問題進行分類。代碼質量問題可分為漏洞、缺陷、壞味道。通過分類及相關的指標反饋,我們可評估代碼的安全性、可靠性和可維護性。
2.代碼質量指標以及計算方法
技術債務、技術債務比率、單測相關指標、重復數等可反饋出代碼質量問題。
(1)技術債務
Sonar平臺通過掃描項目靜態代碼,按照一定公式進行項目技術債務的計算。技術債務反映出修復所有代碼問題(不僅包含掃描出來的靜態代碼問題,還包括代碼運行時的邏輯問題)耗費的時間。該指標值以分鐘為單位,存儲在數據庫中。(一天按照8h計算,默認修復一行代碼耗時30min,可以在平臺的技術債務配置選項中修改這個基準值。)
(2)技術債務比率
該指標值是開發軟件的成本與修復技術債務的成本的比(默認開發一行代碼的成本為0.06天,可以在平臺參數配置中修改這個基準值),反映解決技術債務所付出的成本。
(3)單測相關指標
單測覆蓋率=[可覆蓋行+可覆蓋分支-(未覆蓋代碼行+未覆蓋分支)]/(可覆蓋行+可覆蓋分支)
該指標值反映單測覆蓋了多少源代碼的行和分支。
可覆蓋分支具體解釋如下。
? If語句中一個條件被認定為兩個分支,即一個if語句的分支數=條件數×2;
? 一個for循環被認定為兩個分支;
? ||、&&運算符被認定為(操作數×2)個分支。
單測用例數:單元測試的用例數量。
單測耗時:執行所有單元測試用例所持續的時間。
(4)重復數
重復數包括重復文件的數量,重復代碼的行數。
在檢測重復時,忽略縮進和字符串文字的差異。
3.代碼質量等級劃分
詳細內容可參考官方文檔:https://sonar.yummy.tech/documentation。
(1)代碼可靠性級別
通過缺陷數可劃分代碼可靠性等級,具體如下。
A:可靠性為A,沒有缺陷;
B:可靠性為B,至少有一個次要缺陷;
C:可靠性為C,至少有一個重要缺陷;
D:可靠性為D,至少有一個嚴重缺陷;
E:可靠性為E,至少有一個阻斷缺陷。
(2)代碼安全性級別
通過漏洞數可劃分代碼安全性級別,具體如下。
A:安全度為A,沒有漏洞;
B:安全度為B,至少有一個次要漏洞;
C:安全度為C,至少有一個重要漏洞;
D:安全度為D,至少有一個嚴重漏洞;
E:安全度為E,至少有一個阻斷漏洞。
(3)代碼可維護性級別
根據修復代碼異味計算出來的技術債務比率,我們可進行代碼可維護性評級,具體如下。
A:比率≤5%,評級為A;
B:比率在6%到10%之間,評級為B;
C:比率在11%到20%之間,評級為C;
D:比率在21%到50%之間,評級為D;
E:比率超過50%,評級為E。
所以,我們可以將對項目多維度下的代碼質量等級要求,作為項目代碼質量提升的目標。
1.4.2 搭建可視化數據分析平臺
Sonar平臺是針對項目維度進行分析的,而我們還會在技術中心、部門、人員等維度進行統計分析,若想進行多維度分析,需要搭建可視化數據分析平臺。此時,效能團隊開啟了平臺規劃之旅。
最初,我們為了快,僅僅把Sonar平臺中的數據進行打標簽和字段擴展,經過數據二次加工后轉存到新的數據庫,通過Grafana(一個跨平臺的開源度量分析和可視化工具)進行前端展示。因為平臺的使用比較簡單,此過程相對比較順利。
大概經過2個月時間,我們發現一個很大的問題:隨著度量指標計算越來越復雜,若要整合計算一個指標可能需要跨庫進行多表關聯查詢,執行效率和查詢體驗非常不好。比如一個需求下P0級別的測試用例通過率,需要聯動項目管理平臺、測試平臺以及流水線平臺中對應的數據庫,經過復雜的表關聯邏輯計算得到。
經過一段時間的嘗試,以及考慮到DevOps全鏈路平臺的可擴展性,我們規劃了一個所謂的“數據中臺”(其實就是一個數據倉庫),這樣以后規劃的各平臺都可以通過這個中臺獲取并存儲數據。此部分內容將在第4章進行詳細講解。
接下來,我們就要選取指標了。
如圖1-1所示,這些指標是經過與技術團隊多次討論,并通過實踐證實可有效度量的指標。可將這些指標作為代碼質量度量的指標體系。

圖1-1 代碼質量度量指標體系
1)代碼缺陷:代碼質量可以通過觀察服務運行時的效果來判斷,最直接的就是分析測試出來的缺陷。
服務運行時的效果可反映出業務邏輯的正確與否。若代碼質量較差,線上環境下問題就會很多。于是,我們可以在不同的時間段,按照團隊、項目、產品線等多維度分析缺陷情況,并分析各維度指標的趨勢,如圖1-2所示。代碼缺陷是一個全局性指標,用來初步識別和篩查問題。

圖1-2 代碼缺陷概況分析
我們還可以根據優先級和運行環境進行缺陷分布分析。圖1-3所示為根據優先級進行缺陷分布分析。

圖1-3 缺陷分布分析
2)發布故障系數:聚合分析指標。
服務發布故障系數=服務累計發布次數/服務累計上線工單數,其中,服務的一次部署和發布需要通過至少一次上線工單申請。
團隊發布故障系數=團隊服務累計發布總數/團隊服務累計上線工單總數
發布故障系數反映了一段時間內某團隊或服務在生產環境下一次性部署和發布成功的能力。所以,這個指標主要用來指導團隊進行問題的回顧和復盤。
發布故障系數不為1,則說明服務上線過程中出現多次部署情況,也說明出現了代碼質量問題。不過,我們也需要多維度去分析問題產生的原因,比如,人為操作失誤、溝通不充分、測試不到位、中間件故障、環境不穩定、部署平臺故障等。
團隊維度下的發布故障系數示例如圖1-4所示。

圖1-4 團隊維度下的發布故障系數示例
3)代碼單測:代碼單元測試相關指標。
我們將單元測試覆蓋率指標獨立出來,是因為這個指標不僅是一個局部性指標,也是一個持續性和多維度指標。該指標進一步可細化為5個指標:全量代碼單測覆蓋率、新增代碼單測覆蓋率、單測用例數、單測用例執行耗時、代碼行數。
該指標用來引導研發人員了解哪些業務邏輯代碼被單測用例覆蓋到。對于未被覆蓋到的代碼,測試與開發人員需著重進行測試和關注。按照金字塔分層測試模型,單測指標也可反映技術團隊最基礎的自動化測試水平。其中,單測用例執行耗時指標的考量在于:某個項目的單測用例執行耗時較長,將導致項目構建流水線的整體耗時較長,進而使研發人員因等待時間過長而失去頻繁構建的信心。
一般來說,單元測試工程實踐在技術團隊不好落地。第2章將會詳細講解實踐方法。
我們可按照團隊、項目分支、不同時間段以及不同指標維度進行單測指標分析。圖1-5所示為團隊維度下代碼單測覆蓋率分析示例。

圖1-5 團隊維度下代碼單測覆蓋率分析示例
4)代碼質量:引入能通過Sonar平臺掃描統計出來的靜態代碼質量指標,核心選取的指標包括代碼漏洞數、缺陷數和壞味道數,進而評估各團隊的靜態代碼質量等級。
通過在可視化平臺上設置代碼等級要求,將一些不符合要求的團隊、項目、分支過濾出來。比如ABB等級(安全性A級、可靠性B級、可維護性B級)代表代碼質量良好的服務。這是一個局部過程性指標,可協助一線研發人員多維度分析代碼質量問題。
與此同時,研發人員可點擊可視化平臺上的每個服務鏈接,了解此項目對應分支的最新一次代碼質量詳情;而點擊分析結果中的任何一個問題,Sonar平臺可給出問題產生的原因和建議的解決方法。
團隊維度下代碼質量分析示例如圖1-6所示。

圖1-6 團隊維度下代碼質量分析示例
1.4.3 代碼質量可提升的故事
一個故事至少得有兩條線:一條主線和一條輔線,主輔線交織,方能有效控制節奏,一張一弛才能講出生動的故事。我們要能站在旁觀者視角,根據故事的發展情節,協助主角厘清情節發展脈絡、尋找問題根因、提供解決方法。為了加深觀影者的視覺感知和記憶(抑或警示),我們還需要周期性地植入回憶片段。
下面我們先梳理一下代碼質量提升故事的主線和輔線,根據故事的情節發展,讓各角色都能合理地參與進去,即為各角色選取合適的觀察指標,讓他們能夠根據可視化平臺自助分析團隊問題,通過趨勢圖分析和團隊歷史改進情況,協助各團隊持續改進。
1.故事主線之代碼生命周期
代碼生命周期一般包括5個過程:編寫、編譯、打包、運行和下線,這也是從需求交付到價值交付的全過程,如圖1-7所示。

圖1-7 代碼生命周期
前4個過程對應的核心活動為:編寫單測用例、發現和修復代碼問題、測試發布上線、觀察線上運行效果。
此時,代碼單測、代碼質量、發布故障系數以及代碼缺陷(包含線上問題)等指標,就是我們要關注的核心指標,如圖1-8所示。通過這些指標值和發展趨勢,我們便可驅動技術團隊發現問題,并能夠根據不同角色和不同場景提供相應的解決方法。所以,周期性地改進技術團隊工程實踐方法,并合理地改善這些指標值是我們的使命。

圖1-8 圍繞代碼生命周期的代碼質量指標
于是,我們和技術團隊之間也有了共同的目標:讓每次代碼的發布上線都能滿足業務需求并穩定運行,并形成以代碼生命周期的過程管理為主線,以各階段的全局性和局部性指標改善為輔線的故事發展態勢。
2.故事情節之面向“對象”實施不同的策略
各個角色如何參與到故事中非常重要,如何協調各角色參與到不同的故事場景也很重要。我們負責合理地安排不同角色參與到不同場景,并幫助解決場景中的問題。這樣才能基于故事的主線,順利推動故事情節發展。
下面讓我們介紹如何面向“對象”實施不同的策略,對象具體包括CTO、部門負責人、團隊負責人或小組負責人以及一線研發人員。
1)首先是CTO,他一般不關注細碎的指標、問題解決的具體過程以及采用了哪些詳細的解決方案。
所以,我們與其溝通并選擇了3個“上層建筑型指標”,告知每個指標背后的含義。從此,這3個指標就作為代碼質量委員會每次周會的議題。有了CTO的加持,成功的概率變大。
選擇的3個指標為發布故障系數、優秀單測項目的比例、高質量代碼項目的比例(支持下鉆分析各部門、團隊、產品線維度的指標),這些指標都是全局指標。當然,選擇的這些指標會不斷地變化,以突出不同時期關注的重點。且不同時期對優秀(比如全量代碼單測覆蓋率超60%、單測用例平均執行耗時小于200ms)、高質量(比如新增代碼質量級別達到ABB、線上P0級Bug小于10個)的定義和標準也可能會發生變化。
從此,CTO對技術團隊的要求為:每個OKR周期,3個指標要提升到什么程度,對應各技術部門和團隊的OKR應達到什么程度。
2)其次是部門負責人,他們關注的是整個部門以及部門下各團隊的代碼質量問題。
所以,我們整理了一些部門內和部門間相關的指標,與其溝通并選擇了3個指標作為部門負責人在后續代碼質量委員會周會上匯報的內容。有了各部門負責人的協助,成功的腳步變快。
選擇的3個核心指標為技術債、代碼缺陷、發布故障系數(支持下鉆分析團隊、產品線、服務等維度的指標)。
同時,我們選擇了3個輔助性指標:代碼單測、代碼質量等級、代碼質量,協助多維度分析部門整體情況。
從此,部門負責人向上可承諾每個OKR周期部門要提升的指標以及改善的環節等;向下可基于各團隊現狀要求提升哪些指標,提升到什么水平,進而根據指標決定引入哪些工程實踐,提升團隊哪方面的能力。
從部門管理者視角看,有時候向下管理可能比向上管理更需要“證據”。當發現團隊有問題時,部門負責人不能只說團隊差,要說出具體差在哪里。而效能團隊在一定程度上幫助部門負責人解決了找“證據”的難題。
3)接著是團隊負責人或小組負責人,他們需要關注各小組所負責的服務的代碼質量。(對于微服務,一個系統包含多個服務,一個服務的維護可能需要多個開發成員,一個系統基本是一個底層“作戰單元”。)
選擇的3個核心指標為代碼質量、代碼單測、發布故障系數(支持下鉆分析服務、人員等維度的指標)。
上文有詳細的示例圖,這里不再詳述。
有了這些指標,團隊負責人或小組負責人可實時感知具體哪個系統中的哪些服務出現了哪些方面的問題,找到改進的方向。他們作為戰斗單元的“游擊隊長”,可根據指標現狀,靈活調整改進方案,及時向上匯報改進效果。
4)最后是一線研發人員,他們需要關注自己負責的服務(一般一個研發人員負責一個服務,能力強者可能會負責多個服務),并且需要關注每個服務的代碼細節問題。
所以,我們整理了3個核心指標:代碼質量、代碼單測、流水線構建耗時。
流水線構建耗時長非常影響研發人員頻繁構建的信心,同時長時間等待也會讓研發人員誤認為是CI/CD平臺的性能問題等。流水線構建耗時長的原因需要結合CI/CD平臺、Kubernetes(簡稱K8S)集群、代碼問題、單測質量、基礎鏡像等多維度進行分析。
同時,我們選擇了3個輔助性指標:新增代碼質量、新增代碼單測覆蓋率、新增代碼技術債務。
針對存量代碼規模比較大的服務,我們很難在一段時間范圍內一次性解決所有問題,因此給出的策略就是:重點把控新增的問題,小步解決存量問題。
從此,一線研發人員可根據與各團隊負責人達成的目標,設置好每周新增和存量代碼的質量改進指標;同時,可以結合效能團隊培訓的工程實踐方法,提高自身的工程實踐能力,拓寬知識邊界。
暢想一下:在各位“游擊隊長”的帶領下,有底層“民眾”的支持,再加上高智慧的“計策參謀”,肯定可以在“將帥”的領導下走向成功。
3.故事推波助瀾之趨勢圖
就像看電影一樣,在了解了故事的前后脈絡,掌握了故事主線,知道哪些角色是壞人,哪些角色是好人,但我們還是會想不通:“好人為什么會死?為什么阿珍會愛上阿強?”
我們腦海里不斷回放電影片段,想去弄清楚原因。而隨著時間的推移,我們很難再將這些片段拼湊成一個完整的故事。
如果我們在看完電影后,將主角參與的場景按照故事主線畫一張發展趨勢圖,并將故事角色連成一個人物關系圖,通過趨勢圖,即可找到事件發生的原委。
可見,趨勢圖可幫助推導出事件發生的前因后果,分析出團隊代碼質量的整體走向。比如,在某個時間段指標值整體偏低,可能是團隊放松了代碼質量要求;在某個時間點指標值出現波峰,可能是集中交付導致上線失敗;指標曲線一直呈上升趨勢,說明團隊改進措施產生明顯效果。
(1)發布故障系數指標趨勢圖(支持按照部門、團隊、服務、人員維度進行分析)
從圖1-9中可以看出,該團隊整體的代碼質量非常不穩定,時好時壞,說明團隊成員的能力參差不齊。這種團隊應提升工程實踐能力。

圖1-9 團隊發布故障系數趨勢圖
(2)代碼質量指標趨勢圖(支持按照部門、團隊、產品線、服務維度進行分析)
從圖1-10中可以看出,該團隊的代碼質量在一段時間幾乎沒有改善,一直比較差,需要重點輔助。
(3)單測指標趨勢圖(支持按照部門、團隊、服務維度進行分析)
從圖1-11中可以看出,該服務在某時間節點前全量代碼單測覆蓋率和新增代碼單測覆蓋率都有提升,而在該時間節點后,團隊單測覆蓋率整體沒有進展。這種團隊需要周期性地鞭策和提醒。

圖1-10 團隊代碼質量趨勢圖

圖1-11 團隊單測覆蓋率趨勢圖
所以,趨勢圖可以幫助管理者多維度分析問題,及時調整改進策略。更重要的是,這些歷史數據可以讓部門負責人在代碼質量復盤會上,大膽地展示團隊的努力和戰績。不過,水能載舟亦能覆舟,不是嗎?
謹記:度量指標的選取一定要和各層級負責人溝通并達成一致;指標不是一成不變的,它僅代表你在一段時間內為了解決痛點問題而做出的選擇;在不同時間段,核心指標的重要性、優先級都要根據勢態而調整;一定不要只盯著數據去推動研發人員解決問題,而是要協助他們尋找到解決方法,站在同一條戰線。不要讓研發人員認為你是一個“監督者”和“指揮者”,更不要讓部門負責人認為你是驅趕羊群的“藏獒”,而要致力于成為一頭協助“領頭羊”找到方向的“牧羊犬”。
本節讓各角色認識到:只要團隊稍微不努力,指標數據和趨勢圖就會暴露出團隊的問題。而這些數據都是可視化平臺自動生成的,客觀而真實,和三方團隊本身沒有直接關系。所以,技術團隊各部門只能選擇持續提高自身解決問題的能力。
只有度量指標選得合理,才能幫助團隊發現并解決問題。一切讓數據說話吧!