為什麼好好的開發者,會寫出這麼糟糕的程式?

評論
評論
Photo Credit: Joel Beukelman on Unsplash

原文為《How terrible code gets written by perfectly sane people?》作者 Christian M. Mackeprang 投稿,INSIDE 獲授權編譯。

當我接下把舊 Python 程式庫轉移到 Node 的這份工作,心裏是有點興奮的。這種專案比維護程式要自由得多,而且重寫別人的程式碼有時候還滿有趣的。

不過我們稍微看過要處理的程式後,這種興奮感就消失殆盡了。我知道別人留下的程式碼常常一團亂,但我寫程式 15 年來沒碰過幾次這麼嚴重的案例。先前的作者創造了自己的框架,而它毫無模式可循:沒有做好關注點分離(Separation of concerns,SOC)、混亂的空白和縮排、變數被來自相似卻不盡相同的方法得出的相同數據覆寫、濫用魔術字串(magic string)⋯⋯。

這團混亂簡直就像讓一群只會鬼叫的猴子隨機從 Google 複製一堆程式碼下來一樣。

然而,並非這程式碼慘不忍睹的品質激發了我寫這篇文的動力。而是我在那裡工作了幾個月後,竟然發現寫出這份程式的是一組有經驗且技術精良的資深工程師。究竟是什麼因素,讓一組如此有競爭力的開發者製造,甚至交出這樣的成品?為此我列出了一份清單。

以下是連有豐富經驗的團隊都可能會犯的壞習慣陷阱,而且會嚴重地影響你的最終產品,任何靜態分析工具或開發方法論都救不回來。

「估計進度」大灌水

這份專案很重視截止期限,甚至為此會影響程式品質。當你的開發者把交件看得比寫好程式還重,最終他們得為了讓主管開心而妥協。兩種常見的應對就是做出過量的預期或過度承諾,進而大大地增加工作負擔。

通常要做出過高預期比較困難,因為效果常會即時反映專案成本。  所以開發者可能就會轉而許下過高的承諾。接著他們就只好跳過一些重要的工作,比如思考結構上的問題,或者設計一些自動化機制來解決任務,而去滿足那不切實際的目標和期限。 這些任務通常被視為附加價值,所以被砍掉了也不會發現。當你開始欠 技術債 的時候,產品的品質就會下降,然後因為重整程式碼的成本呈指數型成長,所以直到一切太遲的時候你才會發現。

以這個案子為例,可以看到有些程式碼明顯就是複製來的,但開發者顯然趕著交件,連查一下以前有沒有別人寫過一樣的方法或 SQL 查詢都沒做。

有時候估計本身也可能是假的。比如說敏捷開發有個詞叫「開發速率」(Velocity),是要計算你的團隊多久可以交件,然後做一些微調來加快進度。問題在於,在短期至中期開發間不可能準確地估計速度。就像 平均律(law of averages),通常你無法用過去的表現來預測你現在能做多快,因為情況不同,過去的表現對未來的成果來說不是個有效的指標。

開發者一天其實可以寫很多程式碼,但如果要看完全部的說明文件並花時間和組員溝通,可能 3 天還寫不到 5 行。平均寫多少程式並不能反映出心態準備等重要的資訊。

忽視專案背後的知識

隨著專案推進,你的團隊會學到一些商業上的東西,諸如背後的概念或各項業務之間的連接方式等等。因為在完成前很難完整預知結果,也不知道會碰到哪些挑戰,他們也會在開發過程中逐步了解程式應用的狀況。有些產業比較複雜,更是需要長時間的累積才能消化。

既然我這個專案是改寫舊程式,上述這點影響就特別大。團隊管理層對這項專案了解的程度,會和專案進度息息相關。 如果你負責一項大型專案,裡面的模組你沒經驗又沒人可問,那就得小心了。 改寫程式碼重點就是要利用第一次寫舊程式碼時的背景知識,所以必須格外重視這點。

像我的例子,若找另一組團隊來改寫,那就是揚棄了既有知識,全靠新團隊的技術,卻無法彌補缺乏資訊的短處。 就算是程度普通的開發者重寫自已的程式碼,絕對會比你另外找人做還要更快更好。

甚至聘用也要考慮專案的背景知識。一項專案內含愈多資訊,要讓人跟上進度就愈困難。所以產業知識不只開發的時候很重要,在雇用對的人的時候也很重要,不然你就會跟一組糟糕的團隊卡在一起好幾個月。

追求錯誤指標,比如「完成的 issue」或「每日貢獻」

當評量指標變成目標,就不再是個好指標了。

-Goodhart’s law

在我正漸漸掌握這個專案的時候,有人問我為什麼另一個傢伙完成 issue 的數目比我多,講得好像只要快點交差就是好事。當然可想而知,我只看了他的成品一眼,就在一行程式裡面發現四個錯誤。 聚焦在這種錯誤的指標上會讓你的專案脫軌,而且帶來的壓力不亞於專案期限。

比如「退化率」(regression rate)就是常被忽略的指標。像 null pointer exception 就是要一段時間之後才會顯現的問題,如果你沒注意退化率,那這些 bug 就會不斷從各處突然冒出來,而因為你找錯地方,所以永遠找不到根本原因。

儘管最終極的考量還是呈現給客戶的成果,以及他們對產品滿不滿意、有沒有超越期待。 但要不被貢獻率和 issue 完成數等指標誘惑,卻需要極強的自制力。

要知道指標有沒有用有個好方法,就是試著去了解它代表什麼樣的個人價值。著重那些促進細節、溝通和態度,又很難作弊的指標。

以為好的流程能解決糟糕的人

在企業中,好的流程已經被當成某種萬靈丹。根據我的經驗,一些招聘技巧很糟的大公司,特別愛訂一堆嚴格的規範,好讓糟糕的人也能正常運作。但這卻限制了團隊領導者的創造自由,而且還必須有人先開始正確執行這些流程,後面的人才能跟進。

這是個惡性循環,但只要解決聘雇問題就能根治。 好的人才會自動彌補你團隊中的不足,而這也就是用聰明工作取代努力工作的意義所在。

這些開發者們有時候也特別難溝通。身處一個複雜的程式庫中,我常常得向周遭求援,但是其他人通常都不願放下手邊工作來幫忙。這樣的態度不怎麼好,尤其碰到特別困難、不得不求救的工作時,很少同事同時具有知識和意願伸出援手,這會讓工作壓力倍增。

你需要有常識又有品味,並且敢於指出作業流程哪裡會妨礙進度的人。 每種開發工具、靜態分析工具和通訊工具都有好用和不好用的時候。你需要有人指出不合理的地方,而非盲目地搬來幾個月前在不同情況下用過的流程照本宣科。

忽視實證有用的方法,比如程式碼審查(code review)、單元測試

就算跟著現代最新的軟體開發流程,可能也不足以把脫軌的專案救回來,但想要團隊有競爭力,這點不論如何還是得做。而這就是經過實證有效的方法登場的時候。 用測試來推進專案 ,可以減少 40%-90 的瑕疵; 程式碼審查 也能降低錯誤率,在人工測試下甚至可降低 80%。

想像一下我碰到這種情況有多挫折:我和其中一位舊程式碼的開發者一起工作,而他的螢幕上驕傲地顯示著「筆記本」軟體。在 90 年代光用「搜尋」功能來找方法可能很潮,但現在要是 不能用 IDE、版本控制、程式碼檢查工具,根本綁手綁腳。 現在不管專案大小,這些工具都是基本配備。

想進一步看看軟體開發中已經證實有用的方法,可以參考《Making Software: What Really Works, and Why We Believe It》這本書。它充分列出了近年來已經證實好用又有用的應用方法。

雇用不願交流的開發者

並非所有開發者都不會和人交談。我曾經也是個害羞的開發者,現在還是可以好好地面對觀眾發表演說。

最大的問題還是自己連嘗試都不願意,或覺得增進溝通技巧的要求很煩。相較於上述所有問題,加強溝通技巧是最能加快開發流程的方式。尤其當你藉此拉近距離,分享資訊,就能營造更有熱忱、彼此連結的辦公環境。 就算另一個人遠在好幾萬哩外,只要一通 Skype 就能花 5 分鐘解決原本又臭又長的 coding 馬拉松。

結論

當你用好的工具、實證技巧和良好的溝通來鼓勵聰明工作,軟體開發的過程也會自然流暢。 然而你不能因為採用了敏捷開發或什麼其他的工具,就自動假設其他都不重要,而且事情會迎刃而解。 如果一切都對了,你可以收到讓生產力指數成長的綜效,但要是忽略細節,也可能讓一切陷入又慢又混亂的泥淖。

 

以偏概全的俗語,指用過小的樣本數,來推算普遍情形。

回歸測試發生錯誤的比率。回歸測試旨在檢驗軟體原有功能在修改後是否保持完整,新加入測試的模組,可能對其他模組產生副作用,故須進行不同程度的回歸測試。

相關文章

評論