喂,產品經理喊你回來修Bug~~~

作者:米洛

重新認識網路世界中的bug

我們知道,在網路安全世界中,很多辭彙與它表面的含義大不相同。

不信?安在(AnZer_SH)可以給大家舉幾個例子:

木馬

普通人的世界:通常指遊樂園中的旋轉木馬。王菲的《旋木》里就有這麼一句歌詞:旋轉的木馬,沒有翅膀,但卻能夠帶著你到處飛翔。

網路安全世界:指一種惡意程序,植入受害者的電腦之後,施種者可通過木馬程序任意破壞對方的文件,甚至不經允許遠程控制對方的電腦。

地址

普通人的世界:表示某人/組織所在的具體地點。

網路安全世界:通常指IP 地址/物理地址。所以如果你問程序員的地址,一定要說清是什麼地址,否則你得到的答案也許會是 173.168.15.10,或者是 08-21-6C-06-A6-29。

對象

普通人的世界:對象是戀愛的對方(沒有對象的人怎麼會了解…)。

網路安全世界:對象是類的實例,這個詞通常出現在「面向對象編程」中,與「面向過程編程」相對應。

Bug

普通人的世界:就是蟲子。

網路安全世界:電腦程序中未被發現的缺陷或問題。

好了,現在問題來了!Bug是怎樣從眾所周知的「蟲子」變成程序員眼中最討厭的「漏洞」的呢?(可能有些人已經知道,別劇透,繼續看)

說到Bug,就不得不提到世界上最早一代的女程序媛——Grace Murray Hopper(下圖中的女性)。

20世紀40 年代,為了滿足戰時海量的計算需求,哈佛馬克二號計算機被建造出來。有一天,哈佛馬克二號突然停止運作,就這樣,一隻蟲子(bug)被正式載入計算機史冊。

據說,在1949年9月9日這天,天氣十分悶熱,當時還沒有空調,於是工作人員就把窗戶打開通風。就這樣,一隻bug(其實是蛾子)飛了進來,葬身在了70號繼電器裡面,造成了電路不通,機器死機,程序員們無法算出他們要的結果。

經過一番檢查,最終還是Grace發現了這隻bug,還將它的屍體貼在自己的管理日誌上,上面寫道:「就是這個Bug,害我們今天的工作無法完成。」

【讓Bug名留計算機史冊的管理日誌影像資料】

自此之後,大家都習慣將工作沒完成的責任推給小蟲子,在計算機科學中,「Bug」也就由「蟲子」演變成了程序中的「漏洞」,相應地,「Debug」也從「除蟲」變成了「修復漏洞」。

一個似曾相識的故事

好了,了解完Bug的成名史,現在我們言歸正傳——回到《喂,產品經理喊你回來修Bug》這篇故事,故事是發生在作者身上的一件趣事,不過同為程序員的你一定也遇到過,安在(AnZer_SH)發布出來希望對同為程序員的你能有所啟示:

這個故事你一定似曾相識。

你的代碼很優雅。

你有恰到好處的抽象數量。

你編寫的模塊是模塊化的。

你的系統是通過近乎完美的介面與外部世界相連的,且不直接依賴於外部系統。

你的測試都是綠的。你的代碼覆蓋率報告需要一分鐘的時間才能載入。比率是 97%......

一切都是這麼完美,你甚至已經開始計劃你的完美假期了。

然後,故事總是在不經意處上演。

一個產品經理跑進來告訴你說,上周發布的更新中有個「Bug」。每次當用戶向購物車內添加物品時,購物車裡物品的數量需要幾秒鐘才能更新並顯示出來。以前它是能夠即時更新的。

產品經理告訴你,現在用戶的投訴已經泛濫成災了,並問你:是否能夠幫忙看看?

你當然需要去看看。因為畢竟它是你的「思想結晶」。當然,這也可能是其他地方或人出錯了。但是你決定去修復它,只是因為你就是這種可以扛事的好員工。

你從最新發布版本的提交中提取出Git哈希,並開始研究變更日誌。你已經在最新的發布版本里把 HTTP 請求庫更新到了最新版本。這事已經完成很長一段時間了。你甚至還可以記得做這個變更的確切提交日期。那是個美好的一天。

你立即切換到那個提交,然後模擬更新購物車的請求。好消息是,你做了一個清晰的關注點分離(separation of concerns)。你可以輕鬆地通過一個Build標誌位對模擬環境(staging)和生產環境(production)伺服器進行測試。

PS:軟體應用開發的經典模型有這樣幾個環境:開發環境(development)、集成環境(integration)、測試環境(testing)、QA驗證,模擬環境(staging)、生產環境(production)。

終於,你找到了罪魁禍首!看來是你更新的HTTP庫有一個退化。對於某些特定類型的請求,它需要花費很長時間來解析傳入JSON有效載荷。只有請求解析完成後,你的App才能更新購物車中的統計數字。基礎架構目前還沒有創建來處理最終一致性,要加上它才是一個完全完整的項目。

你不能只是更新本地的統計數字,稍後再同步。

你知道這是其他人的錯,但是你還是要進行修復,沒錯,這就是生活!

你告訴產品經理(PM)是哪裡出現了問題。他拍了拍你的背,用渴望的眼神望向你,請求道,你知道怎麼解決它嗎?

當然!

你對修復計划進行了深思熟慮地思考。

你知道,不能回滾這個更改(rollback the changes)。因為一堆新代碼和Bug修復依賴這個新的庫版本。如果只是簡單地回滾,你將會失去所有一切。

只是簡單地Fork這個庫維護自己的副本(copy)貌似也不明智。原始項目的維護人員有一個巨大的測試框架,它可以基於上千個設備來測試你的修復。你有3個設備,其中2個還運行著過時的操作系統。最好能夠得到他們的反饋,因為畢竟這是他們的庫,他們對其內部結構了如指掌,你而不是。

所以,你準備:

先Fork這個庫(相當於拷貝,因為沒人願意你直接修改原始庫);

clone到本地分支,實現這一bug修復;

發送Pull Request給原始庫;

與原始庫維護者反覆溝通確認;

說服維護者接受你的想法是最好的解決方案;

原始庫維護者接受你的想法,將其merge到他自己的項目中;

等待這個庫的補丁發布;

把庫更新到你的代碼中;

發布一個新版本。

整個過程小菜一碟。

產品經理說,「太好了,你認為整個過程需要多少時間?」

你知道答案。人們總說工程師不能估計時間。但你不是那種工程師。

你毫不猶豫地說,「2 周,當然這也取決於這個PR被接受的速度,以及維護者發布新版本的速度。」

產品經理的臉色突變。反覆喃喃道,「2 個星期?2 個星期?」

你繼續保持安靜,彷彿可以預測到產品經理下一刻就會勃然大怒。他憤憤地說道,「這麼久我們的用戶會流失的!購物車無法實時更新,他們不會再來買任何東西的!我們是一家電商公司!這是絕對不能接受的!」

你期待他能夠在悲憤後坦然接受「兩周」的結果,但是顯然沒有,他看起來陷入了討價還價模式。他接著道,「沒有什麼辦法可以更快地解決它嗎?有沒有臨時方案?拜託了!速度真的很重要!」

你坐在旋轉座椅上,悠悠地說,「好吧,讓我再想想看。」

你決定讓步一點,儘快打發他離開,畢竟你手頭還有一大推其他事情要忙。

你再次潛入源頭,研究代碼。這是你的本行,只見你的手指按著IDE快捷鍵,就像波塞冬(希臘神話中的海神)在海浪中馳騁。

啊哈!找到了!有一個無記錄的方法能夠為JSON 解析代碼加上鉤子,並將其替換為你自己的實現!

但是等等。這看起來有點醜陋。它是一個非開放的 API。可能是被錯誤地暴露出來的。你不想依賴於這個。因為如果他們在下個版本移除了它該怎麼辦?這樣的話,你將必須重做一次。誰想這麼做?雖然這比維護你自己未經測試的分支更快,但不可否認的是,它依然是醜陋的。

不!絕不可以,你不允許商業決策破壞你純潔的殿堂。你是所有神聖事物的守護者,要反抗無知的大眾。這是他們付給你大價錢的原因。你有責任拒絕。

你衝進產品經理的小屋,告訴他,「答案是沒有!沒有更簡單的辦法來解決這個問題,對不起。」

他的反應可想而知,他說,「你跟我說有辦法,但是你不想去做,只是因為它不整潔?我們的用戶正在投訴我們,他們隨時會加入競爭對手的陣營,但你現在不願意去修復,僅僅是因為這(方案)不整潔(clean)?」

你無語了!這傢伙了解工程么?你用bit從無到有地構建出一個虛擬的世界。高度可擴展的系統可以抵禦來自前蘇聯集團所有黑客的DDos攻擊。你是個藝術家,矽片是你的畫布。你讀過很多遍《Clean Code》,所以你了解它的程度超過了你自己的 Github密碼。

你大聲喊道,「是的!我不想讓這個垃圾玷污我們的代碼庫!我花了幾個月的時間來構建這個!每一行代碼都是我血汗的結晶!所有事情能夠運轉正常的唯一原因不是因為你!是像我這樣的人在維護軟體運行,是像我這樣的人在幫你們清理爛攤子,幫你們完成業務。」

你發泄完覺得需要喝點東西。你認為像這樣的傢伙是行業的禍害。他們以為自己的MBA經歷會賦予他們構建偉大軟體的洞察力,而我們開發人員則被他們忽視。去他們的!

你憤憤難平地來到自助餐廳。你每天都會來這裡享受美食和咖啡——無限續杯的,美味的,滋養靈魂的咖啡。你值得這一切美好,因為你是知識型人才。

你拿起一杯Java(爪哇)咖啡,找個地方坐下來。

這時,你注意到了他——你們公司最高級的工程師。

這傢伙是個地道的、專家級的,用上廁所的時間就能寫出編譯器這種類型的工程師。他以前是黑客大牛,你想成為這樣的人,你覺得他有些像甘道夫(北歐神話人物),在受到大家尊敬的同時也為人所恐懼。但他其實是善良的,經常會幫助小輩。

你想他一定會樂於聽到你說如何搞定那個產品經理的事情,畢竟,他也和你一樣是工程師。

於是,你坐在他旁邊。他正攪拌著自己的咖啡,在閱讀Haskell抽象數據類型相關的內容。

對,正好跟這個傢伙聊聊。

你告訴他剛才辦公室發生的事情以及你的「雄言壯語」。他耐心地聽著,不時地點著頭,問了些問題。他的身體語言在傳達他是輕鬆隨和的,這一切也可以從他的眼中讀到。

你終於說完了那件讓人精疲力竭的事情,你感覺自己的雙肩輕鬆了許多。

他看起來陷入了沉思,好像在仔細地組織著語言。你在等著他會驚呼,「幹得漂亮!」然後你們一起再續一杯咖啡,等著聽他講述發生在他自己身上的另一個類似的故事。

你夢見過這一天。在「鬥爭」獲得勝利後,你與身邊的人舉杯共慶。就像電影中的情節一樣,當然,他們通常喝的是啤酒,而不是咖啡。

你就這樣一邊幻想一邊等著他的答案……

終於,在漫長地等待過後,他直視著你的眼睛,像是能刺穿你的靈魂。多少年來與機器打交道弱化了他的視力,但這種注視卻散發著迷人的力量,讓你無法擺脫。

他只說了一句話,「我們的工作不是喝咖啡、折騰代碼。我們的工作是創造能夠運行的軟體。」

然後,他走開了。

你愣了一分鐘。胃裡產生了翻江倒海的感覺,你突然重新認識了這種感覺,你感到恥辱。你辜負了你欠得最多的人——你的客戶。

於是,你回去辦公桌前,你搞定了那個「不整潔的代碼」,然後推出了一個新的版本。

接著,你去向那個產品經理道歉。事情變得有點失控。他說沒事。所有事情都進展順利,也沒有造成難以挽回的後果。

你也fork了這個庫,實現了正確的修復,並發出了主庫的PR。當庫的新版本出來時,你總是可以重構的。

一件看似尋常的小事,一次次內心的掙扎,我想作為程序員(尤其是有精神潔癖)的你,一定也經歷過這樣的時刻,但是請永遠記得,「我們的工作不是喝咖啡、折騰代碼。我們的工作是創造能夠運行的軟體!」

安在

(ID:AnZer_SH)

新銳丨大咖丨視頻丨白帽丨深度


推薦閱讀:

你知道國內有多少 SRC 嗎?
Linux堆內存管理深入分析(上)
安全債務是工程師的問題

TAG:网络安全 | Bug | Bug修复 |