1. 程式人生 > >PM 叫你去改一個 Bug,後來……

PM 叫你去改一個 Bug,後來……

你曾經碰到過現在這種情況:

  • 你的程式碼非常優雅。
  • 你程式碼中的抽象剛剛好,不多不少。
  • 你的模組都各自獨立。
  • 所有的測試結果都是綠色的。程式碼測試覆蓋率報告花了整整一分鐘才打開,上面顯示著 97%……

生活很美好。

然後事情就這麼發生了。

一個 PM(產品經理)跑進來,跟你說上週你釋出的那個更新裡面有個 bug。不論什麼時候,只要使用者在購物車裡添加了一件商品,購物車中的計數過個好幾秒才會更新。本來應該立即更新的。

PM 跟你說使用者的抱怨如潮水般用來,他問你:你能看一眼麼?

當然你能看一眼,畢竟這是你做的東西。很可能是其他什麼人犯了錯。不過你會修復這個問題的。你就是這麼正直的員工。

你在 Git 上把最新的釋出版本同步下來,然後開始研究變更日誌。在上一個釋出版本中,你把 HTTP request 庫更新到了最新版。那次稽核過了好長的時間。你還能記得這次修改確切的提交所在,那天的天氣不錯。

你切換到那次提交,然後模擬了一下更新購物車的請求。不錯 ,你已經充分考慮到了程式碼的獨立性,可以很容易地在測試環境和生產環境中進行測試,只需要切換一個構建標記就夠了。

你找到了那個罪魁禍首。看起來你更新的那個 HTTP 庫有個迴歸(regression)。對於特定型別的請求,它花了太長的時間來解析傳入的 JSON 負載。你的應用只能在請求負載解析完成之後才能更新那個計數器。在架構上還沒有處理最終一致性的問題,要加上這種設計的話,本身就足夠當成一個專案來做了。所以你沒法在本地先更新計數器隨後再同步到伺服器上。

你知道這是別人犯的錯。唉,這就是生活。

你把事情的原因告訴了 PM。他拍了拍你的背,知道這不怪你。你能把這個問題修復麼?

當然。

你已經考慮好你的解決辦法。

你不能把變更都回滾。有一大堆新的程式碼和 bug 的修復都依賴於這個新版的庫,要是你把所有東西都回滾的話,這些就都白乾了。

只是把這個庫 fork 下來然後維護一個你自己的版本看上去也不太可行。之前這個專案的維護者有一個超級完備的測試架構,會在上千臺裝置上測試你修復的程式碼。而你只有三臺裝置,其中兩個的作業系統版本都老掉牙了。最好還是需要他們的反饋,畢竟這是他們維護的庫,他們對其內部結構很瞭解,而你不瞭解。

所以你打算這麼幹:

  • Fork 這個庫
  • 實現程式碼修復
  • 向原始的 repo 中發一個 pull request
  • 你和維護者可能需要來回幾次溝通
  • 最終說服他們相信你的方法才是最好的
  • 程式碼合併
  • 等著這個庫釋出一個新的補丁
  • 在你的程式碼中更新這個庫
  • 釋出產品的新版本

很簡單嘛。

“好極了,”PM 說,“你覺得需要花多長時間?”

你知道這個答案。人們都說程式設計師不會估算時間,你可不是那種程式設計師。(《為什麼軟體開發週期通常是預期的兩三倍?》)

“兩週,”你眼都不眨地說,“取決於這個 PR 多久才會被接受,還有維護的人多快能釋出一個新版本。”

PM 的臉色立刻就變綠了。“兩週?兩週?!”他重複著同樣的話,好像這樣能改變一樣。不過他還是保持了冷靜。PM 知道怎麼處理負面的情緒,沒什麼可擔心的。

“我們的使用者正在流失!他們什麼都不會買了,因為他們沒法看到自己購物車裡面的更新!我們是個電商公司!這是不可接受的!”

你看著他經歷著悲傷的五個階段(譯註:否認、憤怒、討價還價、絕望、接受)。你等著最後接受的那個過程什麼時候會發生。不過並沒有。他看起來停在了討價還價的階段。

“好吧,”你說著,深陷在你的轉椅裡,“讓我想想。”

你會遷就他一下下,然後他可能就會離開了。你還有很多其他事情要做,你知道的。

你開始翻看原始碼。這是你的特長,你的手指敲擊著 IDE 的快捷鍵,就好像海神波塞冬駕馭著大海的波濤。

啊哈!你找到它了!有個文件中沒提到的方法,可以在 JSON 解析的程式碼中插入一個鉤子,然後用你自己的實現來替換它!

不過等等。這看起來太醜陋了。這可是個非公開的 API,說不定把它暴露出來是個意外呢。你可不想依賴這種東西,萬一他們在下一個版本里把它移除掉了怎麼辦?那樣你就得把這套東西整個都重寫一遍了。誰想這麼幹啊?不過這確實比自己維護一個沒測試過的分支要快一些。不過還是太醜陋了。

不要。

你可不想因為商務決策而誤導你,毀了你純淨的神殿。你是神聖的守護者,對抗著那些愚昧的事物。這就是為什麼他們會付你那麼多錢的原因。你的責任就是拒絕這種要求。

你衝進 PM 的屋子。“答案是不要。沒有什麼優雅的方法來解決它,我不相信醜陋的旁門左道。抱歉。”

他的反應和你預料中的一樣。

“你告訴我有個方法可以做到,不過你不想這麼做就因為它不夠優雅?我們的使用者正衝我們叫囂著,威脅我們要改用我們競爭對手地產品,而你就不願意修復這個問題,就因為它不夠優雅?“

你失敗了。

這人懂什麼軟體工程?你只用程式碼就憑空建立了這個奇妙的世界。高度可擴充套件的系統,可以抵抗住來自前蘇聯集團中所有黑客發向你的 DDoS 攻擊。你是個藝術家,而晶片就是你的畫布。你已經無數次地閱讀了《程式碼整潔之道》,你對它的瞭解甚至超過了你對自己 GitHub 密碼的印象。

“沒錯!”你喊道,“我不會用這種垃圾來玷汙我們的程式碼庫!我花了好幾個月才構建出這些東西!產品裡的每一行程式碼都是我的心血!它們能夠正常執行的唯一原因不是你,和你沒關係!是像我這樣的人們維持著軟體的執行,是像我這樣的人們,不得不在你和你的那些‘商業功能’完成之後去清理那些亂七八糟的東西!”

你衝出了那兒。你需要喝點什麼。這樣的人簡直就是業界的禍根。他們覺得自己那些花哨的 MBA 證書能讓他們知道該如何創造出偉大的軟體,而我們這些開發者卻不知為什麼忽略了這種方法。

你昂首闊步地走進休息區,那是你每天享用那些美食家們推薦的午餐的地方。還有咖啡,不限量的、美味的、滋潤著你的靈魂的咖啡。你值得這種享受,因為你是個知識工作者

你衝了一杯 java 咖啡,想找個地方坐下。

然後你看到了

你的公司中最資深的程式設計師。

這傢伙是個徹頭徹尾的核心人員,是那種“我在上廁所的工夫就能寫出一個編譯器”的程式設計師。在黑客出現之前他就已經是名黑客了。你想要成為這樣的人。他就像是指環王裡面的甘道夫。這裡所有人在所有時候都尊敬和畏懼著他。不過他很和藹,總是會幫助那些孩子們。他應該願意聽聽你和 PM 之間發生的事情。畢竟,他是你這一夥的。

於是你坐到他旁邊。他正享受著咖啡,正在看著什麼 Haskell 中抽象的資料型別之類的東西。

沒錯,就得和這樣的人聊聊。

你把自己的壯舉告訴了他。他耐心地聽著,偶爾點點頭,問了些問題。他的肢體語言是向後靠著。從他的眼神中你能看得出來,他以前也經歷過這種事兒。

你終於說完了。

好累。

你感覺肩上的分量輕了一些。

他看上去陷入了沉思,好像正在謹慎地選擇著詞彙。

你等著他會大笑著宣佈“乾的好,孩子!”,然後你們會一起再衝杯咖啡。他會給你講一個他所經歷過的類似的故事,在那一天,他如何斥責一個愚蠢的 PM。

你曾經夢想過這一天。你們會用咖啡碰杯,就像那些在戰場上取勝的戰士那樣。至少,在電影裡他們是那麼幹的。當然,他們通常用的是啤酒,而不是咖啡。

在感情上,你是這麼希望的。

你等待著……

繼續等待著……

他直直地看向你的雙眼,穿透了你的靈魂。那些和電腦一起奮鬥過的歲月讓他的目光變得如此難以忍受,不過他使用了什麼魔法,讓你無法移開你的眼睛。

他只說了一件事。

我們的工作並不是喝喝咖啡敲敲程式碼。我們的工作是編寫能夠正常執行的軟體。

然後他就走開了。

你呆住了一分鐘。在你肚子裡有種什麼感覺,一種空蕩蕩的、噁心的感覺。你開始意識到這種感覺,叫做羞愧。

你讓那些你最虧欠的人失望了,那就是你的使用者。

於是你回到自己的座位上,迅速搞定了那個“旁門左道”,然後釋出了一個新的版本。

你向 PM 道了歉,自己有點失控了。他說沒事。最後只要沒事就好。

你還是 fork 了這個庫,實現了一個正確的修復方式,然後提交了一個 PR。當這個庫以正確的解決方法釋出新版本的時候,你總是可以重構自己的程式碼的。

打賞支援我翻譯更多好文章,謝謝!

打賞譯者

打賞支援我翻譯更多好文章,謝謝!