CODING DevOps 系列第四課:DevOps 中的質量內建實踐

CODING_DevOps發表於2020-06-18

什麼是質量內建

隨著時間的推移,我們專案的開發效率會逐漸降低,直到幾年之後整個專案可能就無法維護,只能推倒重來。具體的表現首先就是隨著時間推移,我們會發現整個需求列表裡面能做的需求越來越少,因為每當我們增加一個新特性,需要改動的程式碼就非常多,所以最後每提出一個新的需求,團隊評估出來的改動成本都非常高,導致最後難以增加新的特性。

第二個表現就是缺陷難以修復。我們做出來的系統只要有人用就會有反饋一些線上的故障,一開始程式碼很簡單的時候修復起來是很快的,但是隨著程式碼越來越複雜、程式碼行數越來越多,我們會發現定位問題太難了。尤其是現在我們的專案採用的是非常複雜的架構,所以當使用者線上報錯的時候,我們很難去定位到是哪裡出了問題。但其實只要定位到了問題,修復起來是很快的。

第三個表現我們稱之為“打地鼠現象”,簡單來說就是當你“按”下一個缺陷的時候,又會蹦出來幾個新的缺陷。這樣會導致大家在工作的過程中壓力非常大、心情也會比較沉重。

1

所以對於這些挑戰,我們也有想辦法去解決,CI、CD 以及 DevOps 的出現都讓我們看到了很好的方向。但是我看到很多團隊其實只是靠 DevOps 解決了一些基本的問題,並沒有解決核心的問題。這是為什麼呢?因為核心問題主要是靠開發人員的能力提升來解決的,但由於改變一個人是很難的,所以企業往往會繞開這些問題。所以我今天分享的內容主要會涉及到開發人員如何去寫程式碼等一些實踐。

我們在剛開始啟動一個專案的時候,我們會制定一些程式碼規範,所以程式碼相對來說是比較清晰的。但是隨著需求的演變,在實現這些需求的時候,每個人都會選擇最低成本、最保險的方式。這就會導致沒有人敢去大幅度地改動程式碼,只會在裡面追加一些程式碼,造成了程式碼裡面有大量的重複、過長的方法。同時開始的時候設計的架構也是非常清晰的,但是如果後續沒有很好的落地、監控、自動化地發現問題,架構就會在這過程中腐化,變得一團亂。

Deming 先生曾提出“問題發現得越早,修復的成本越低”,這句話也是我們去降低軟體開發成本、更高效地保證質量的重要原則。所以我們採用質量內建的方式,可以把整個軟體質量的保障內嵌到開發的過程中去,而不是留到後面再去檢測,因為越往後修復的成本越高。

85% 的缺陷都是在程式碼編碼階段引入的,然而大部分的缺陷並不是在編碼的時候發現的,而是在後面的單元測試、功能測試、整合測試發現的,越往後發現的缺陷越多。按照剛剛那個原則,假如在編碼階段發現的缺陷只需要 1 分鐘就能解決,那麼單元測試階段需要 4 分鐘,功能測試階段需要 10 分鐘,而到了上線之後再發現可能就需要 640 分鐘,這個成本是非常高的。

2

那麼質量內建的方式是怎麼樣的呢?首先我們通過自動化測試、重構、簡單設計等手段,可以使在編碼階段引入的缺陷變少,因為我們程式碼寫清楚了,bug 就藏不住了。同時當我們做到自動化測試等工作時,在編碼階段發現的缺陷也變多了。那麼通過質量內建,我們在編碼階段就把大部分的問題都捕獲到,同時引入的缺陷也更少,它就降低了軟體的開發成本。

大家可能會有一個疑惑,就開始開發人員原本只用寫功能就行了,現在卻還要寫測試程式碼,而且測試程式碼的比例和實踐程式碼的比例不一定,這樣會不會增加成本。這裡想跟大家說一下,很多人會把我們編寫程式碼的時間當成整個軟體開發的時間,其實不是。在編寫玩程式碼之後,還得開發自測,然後還要去聯調,之後還要進行內部測試、線上故障修復等,所以整個軟體開發有這麼多的過程,而我們現在解決問題的辦法是在第一階段投入更多的時間,做更多的測試、更多的程式碼優化等,從而減少後面所要花費的時間。根據剛剛說的修復時間越晚,成本越高的原則,我們這樣做是划算的。

3

技術債與質量門禁

技術債是什麼呢?債是一種比喻,與我們金融方面所說的債務意思相同,那麼在我們技術範疇裡面也有這樣的債務問題。在我們編寫程式碼的過程中留下了一些重複的程式碼,或者沒有起好名字、沒有給出註釋,類似這樣的問題就是我們欠下的技術債。

對比金融裡的債務,技術債也有相應的特性。首先這個債我們必須得還,否則到了後面越欠越多可能會把整個團隊壓垮了,導致大家沒有動力去開發新的功能。同時技術債是有利息的,假如最開始寫程式碼的人留下了問題沒有去解決,那麼下一個接手這個程式碼的人可能就沒法理解這個程式碼,就不敢大膽地去改程式碼,越晚就越不敢。

既然技術債存在這麼多問題,大家為什麼還要去欠債呢?因為技術債也有好處,有的時候我們要做的產品並不是一個非常靠譜的產品,我們就會追求更快,用一個比較粗糙的手段做完交給客戶去進行測試。得到反饋之後,靠譜的話我們就會用心去優化、迭代;不靠譜的話我們就會放棄這個專案,這是它的成本也很低。所以由於網際網路行業的這種快節奏,人們會傾向於欠下很多的技術債務,從而快速試錯。當我得到反饋,確認使用者的痛點之後再來進行程式碼的優化。當然我今天更想講的我們為什麼會欠下債務,其實還是是因為態度以及習慣問題。如果我們能改掉我們的壞習慣,我們就會少欠下一些技術債。

當我們搭建好一個專案的基礎框架,寫了一些示例的程式碼,後面就會上很多的人來做一些新需求。這個時候就會出現“失控”,我們會發現一開始的程式碼非常整潔,但是人一多之後就會形成“破窗效應”——簡單來說就是一旦一扇窗戶上出現了一個破洞,那麼很快上面的破洞就會越來越多。程式碼庫也是如此,當一個人沒有按照規範寫程式碼,同時沒有人制止,那麼很快其他人也會紛紛開始這樣做,很快程式碼就會變得亂七八糟。

那麼應對這種“破窗效應”的方法就是“童子軍軍規”,就是不管原來的質量怎麼樣,我們也得保證我們接手處理完之後,程式碼的質量要比原先好上一點、乾淨一點,哪怕是改一個變數命名也好,改一個格式也好,人人都這樣做的話我們的程式碼庫就會越來越乾淨、質量越來越高。這種方式就是我們所謂的“質量門禁”。

接下來講一下償還技術債,首先第一點是並非所有技術債都應償還,或者說技術債的償還應該有一個優先順序,我們更應該關注的是那些頻繁地需要變更的程式碼。第二點是應用童子軍規則,也就是有債就還,不要拖欠太久,保證每次提交程式碼的時候比接手時要乾淨一點。第三點是先償還高息技術債,就是看哪些問題不處理的話帶來的後果會更嚴重,我們就優先處理這些問題。接著是分期償還技術債,將我們的技術債管理起來,每次迭代的時候就一邊做有客戶價值的工作,一邊償還技術債。這裡很關鍵的就是不能依賴開發人員的自覺性,而是在迭代的時候就要明確那哪一塊要優化、要重構,分到個人的頭上,同時後面要進行評測、驗收,經過這樣一個流程正式地去對待技術債。

4

自動化

自動化是一個實踐,我們經常會聽到像自動化釋出、自動化打包、自動化構建、自動化測試等,尤其是自動化測試是一個反覆被強調的一個實踐。我們的流水線其實整個都是自動化的,構建是自動化的,檢查是自動化的,包括後面的測試和部署也都是自動化的。

5

有一個原則叫自動化一切,就是“一切能被自動化的都應該被自動化”。除了常見的編譯、檢查、測試和部署,伺服器的配置也可以進行自動化,甚至業務上的一些部署,比如一些遷移之類的,能自動化的我們都把它自動化。我們作為開發人員,最擅長的其實就是寫程式碼,很多人會覺得自己的工作沒什麼挑戰,這是因為你天天都在手工地做一些重複的事情,當然沒有挑戰了。這時候你可以嘗試去自動化一些事情,你會發現很好玩,也能學到新的東西,個人能力能得到成長,同時做的事情也有價值。

我體會到自動化的幾個好處,跟大家分享一下。第一個是沉澱知識,就是把知識沉澱到了自動化的指令碼里面,而不是存在於某個人的腦子裡。而對於掌握知識的這個人來說,他也減少了被打斷的可能。第二點就是自動化能夠提高效率,解放生產力,這一點其實是一個很明顯的好處,原來手工要花五個小時的事情,自動化可能幾分鐘就跑完了。最後一點就是固化流程,降低出錯率。也就是將我們的這個流程固化下來了,原本一件事情今天是 A 做,明天是 B 做,他們在做的時候可能就基於自己的理解來做,中間就會引入一些錯誤。而自動化就可以規避這種問題。

6

其他有效實踐

①結對程式設計:結對程式設計是我非常推崇的實踐,很多人認為結對程式設計就是一個人寫一個人看,這樣就浪費了一個人,其實不是的。其實結對程式設計有點像汽車拉力賽,領航員會看地圖然後告訴 driver 前方的路線,例如前面的彎道該怎麼走,所以他的視野會更加巨集觀,看得更遠,也有助於對我們的 driver 做一個思維上的引導。寫程式碼的時候也是這樣的,操作鍵盤的人在考慮程式碼該怎麼敲,而另一個人則是在引領思路,所以他倆是在互相配合的。

7

②程式碼評審:程式碼評審就是大家坐在一起,分享程式碼的收穫、踩過的坑以及解決問題的方法、技巧。這是一個開發人員的交流活動,而不是一個類似於質量門禁的東西,這是有溫度的一場交流、分享,傳播有價值的東西。

8

③暴徒式程式設計:暴徒式程式設計是結對程式設計的一種方式,由一個人操作鍵盤,同時設定定時,每隔一段時間換人。其他人就負責盯著大螢幕告訴他該怎麼操作,這個也是一個很好的學習手段。

9

小波老師將在完整視訊中繼續為大家帶來
更多精彩分享以及重構的線上演示
點選觀看完整視訊

相關文章