軟件開發中的上游思維

最近學習了萬維鋼老師解讀的新書《上游:在問題發生之前解決問題》,收穫不少。聯想和類比自己從事的行業,談談一些淺顯的體會,也能借鑑書中的思想。
上游
首先,上游思維有三個條件。

眼光

在別人發不現問題時,你能看出問題。

這裏的重點是問題不易被察覺,因而目前不是緊急的事情。如果問題大家都能看出來,可能很快就被解決,也就失去上游的意義。如果問題亟需解決,不然就會遭受巨大損失,那麼也沒有上游的意義。

你發現軟件系統裏有個潛在的bug。這個bug有這樣兩個特點,一是發現它需要對代碼邏輯和架構非常熟悉,而且要有豐富的調試和排查經驗。二是這個bug在大多數用戶場景不會出現,不會嚴重影響用戶體驗。

那麼這個bug的就是上游的問題,但是作爲資深工程師的你發現了它,並不一定回去解決,這就涉及上游思維的其他條件。

責任

有時候問題不是沒人發現,而是沒人願意負責,這就會出現所謂“不注意盲點”(inattentional blindness)。在制度上安排特定的人負責是一種辦法,但畢竟外在壓力不如內在動力。如果有人主動願意負責,消除盲點,就會及時發現並解決更多問題。

上面那個bug是屬於系統A模塊B的,而你是負責模塊C的開發與維護,那麼很多工程師判斷是不是該主動解決這個問題時,可能會採取責任>能力的原則:我能修掉,但這不是我該做的。

這確實是一個比較現實的問題,在一個組織中,不同團隊的合作不僅僅是技術交流和分工那麼簡單。每個團隊都有自己目標和資源,這些也可能與考覈掛鉤,開發資源的使用會比較慎重。然而,如果能夠準確發現問題,就已經是上游思維了。

資本

這裏的資本不一定是指財富和社會地位,而是一種自由的、有“餘閒”的精神狀態。

如果一個軟件工程師每天的日程排的滿滿的,他的精力應付自己的開發任務尚且不足,更別提一些不必馬上做的事了。

想要所有工程師都有“餘閒”去處理上游的事情不太現實,然而但凡有些條件的同仁們可以想想自己的時間安排,是否能夠規劃固定的餘閒時間來處理一些重要但不緊急的開發任務呢?長期來看,這些餘閒的積累可能給你和團隊帶來驚喜。

上游思維還有七個方法。

系統思維

以前我聽到系統思維,總是理解爲要綜合考慮問題,其實這只是一方面。好的系統應該是不用時刻考慮方方面面,一切都是自然的、井井有條的,從而感覺不到系統的存在。設計軟件系統和流程也可以借鑑這個思想。

如果我們在開發一個軟件系統時發現,同類型的問題經常出現,並且不易察覺和調試,那麼很可能原來的系統架構設計就有問題。這時一次重構也許是必要的,而不是頭痛醫頭腳痛醫腳。

很多系統尤其是運維(DevOps)團隊的系統,其實可以實現一些自我反饋的算法和邏輯,當系統出現問題,自動採取一些修復的動作,最大限度減少人爲的干預。畢竟,人爲干預可能引入新的問題。

聯手解決

讓不同背景的人共同參與討論和實現,可能是高效的做法。只是人多還不夠,還需要多樣性。

一個開發團隊如果有不同技術背景的工程師,那在遇到難解的問題,或者進行架構設計時,就會獲得從不同技術角度得出的思路和想法。避免因爲團隊整體的技術短板,導致開發結束才暴露出設計上的缺陷。

尋找支點

支點是系統中最關鍵或者最危險的因素,但由於分佈的不均勻,並不容易發現。數據分析是判斷支點的工具。有些“壞事”的模式還可能隱藏的很深,只有數據還是不夠,更需要好的分析方法。

每個開發團隊都會額外開發一些監控系統、日誌收集和分析系統或者bug分佈圖表等,目的是分析軟件產品在實際運行中的表現,好在哪裏、壞在哪裏可以一目瞭然。

這些數據有助於團隊決策者調整研發和測試的方向,最終提高產品的體驗和質量。有時,趨勢和瓶頸不是那麼明顯,還需要藉助機器學習算法來輔助分析,進而發現一些潛在的、有用的模式。

上游思維

提前預警

預警是通過一些蛛絲馬跡對即將可能發生的“壞事”提出警示,將一些惡行扼殺在萌芽中,防患於未然。預警也常常依賴於對數據的收集和分析。

識別“假成功”

警惕三種假成功:跟隨大潮的、靠運氣的成功;找出替代方案迴避原始問題的成功;完成指標傷害使命的成功。

程序員們可能都有這樣的經歷,有時候代碼正常運行需要靠“運氣”,產品上線前要找個“祖師爺”拜拜。這當然不是長久之計,軟件程序正常運轉不代表軟件沒有問題,尤其是你已經意識到程序某個部分可能有問題、但實際沒有問題發生的時候。

此時最關鍵的做法是分析運氣成分,即爲什麼明明有潛在問題而沒有出問題。當然,很多人覺得還有更緊急的事情要做,但欠的債早晚要還的。如果它可能出問題,那麼早晚會出問題。

尋找替代方案(workaround)也是類似,替代方案可用會讓你放鬆對代碼質量的把控,這樣可能導致冗餘、擴展性差、耦合性高的代碼。一時的成功可能是未來的大坑。

開發流程中也有各種指標來評價和規範流程,比如測試的覆蓋率、bug的修復率等等。過度關注這些指標,可能會忽視代碼的功能本身。一個開發者可能爲了滿足一些靜態代碼掃描工具的指標,而放棄原有的代碼結構,而原有的結構可能是質量更高的。

反饋

你照顧系統的部分,就可能會傷害整體;你從整體考慮,又可能會傷害某個部分。要想盡量避免傷害,你需要反饋。及時的反饋有助於發現一些行爲的二級效應或者副作用,這可能需要走一步看一步,先做一些試點,再慎重推廣。

在軟件發佈階段的測試裏有一種方法叫“金絲雀(Canary)測試”。大致的思路是,先讓產品部署到一小部分用戶羣體中,看看是否有嚴重問題出現,根據反饋的結果決定是否擴大部署範圍,最終產品會部署到所有用戶終端。很久以前,煤礦的礦工就是放一隻金絲雀到井口,看看是否有毒氣出現。

讓人買單

找人爲上游的行動買單,就要找到利益相關者,並讓他相信上游的問題確實會出現,解決問題確實會帶來收益。

有時工程師會對產品的流程或者設計提出優化方案,這可能需要額外的人員支持,管理和開發工具的購買,已有流程和工具的調整等等。

這就需要說服利益相關者採取行動,你需要給出對比的數據,在優化前是什麼表現,優化後提升了多少,這些提升是否能成爲改變的理由。有時不同團隊之間的溝通和說服,還需要向上尋求幫助,從更高層的戰略角度來向下推行,這取決於公司的結構和文化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章