在發現自己能夠將舊的Python代碼庫移植至Node中時,我感到興奮莫名。相較于普通代碼維護工作,這類移植任務往往擁有更多創作自由與發揮空間,且在樂趣層面遠遠超過修改他人留下的代碼爛攤子。
然而在開始實際工作之后,這種興奮感迅速消失。雖然我已經擁有15年的編程從業經歷,但其中的遺留代碼仍然相當恐怖,甚至可以說是我所見過的最糟糕的代碼庫之一。原作者構建起自己的框架,且其模式與完美一詞基本背道而馳:關注點未進行拆分、縮進時亂用空格/tab、同一概念擁有多個名稱、來自內容幾乎相同的不同方法的同一數據多次覆蓋變量以及魔幻般不可解讀的字符串……這一切都證明,這套代碼庫絕對是之前某位碼農通過復制谷歌查詢結果拼湊出來的成果。
然而,這種徹底違背編程規范的狀態反而引發了我的興趣,并促使我寫下這篇文章。經過幾個月的工作之后,我發現原作者實際是一位經驗豐富的高級開發人員,且擁有出色的技能水平。那么到底是什么原因導致這位主管人員編寫出如此垃圾的代碼?立足于此案例,我整理出一份原因清單。 其中條目為即使是經驗豐富的團隊中也普遍存在的種種壞習慣,其會直接體現在最終產品當中,且任何靜態代碼檢查工具或者開發方法都無法對其加以糾正。
1.對重要性太過高估
此項目中的一大缺陷在于過度關注截止期限,甚至以損害代碼質量為代價。如果開發者過度關注項目本身的重要性與交付時間,而非編寫良好代碼,那么其最終結果絕對會令企業管理者更加頭痛。造成這種問題的根源有二,其一為過度估量、其二為過度承諾,而二者皆會增加開發者負擔。
一般來講,過度估量的可能性相對較低,因為項目成本往往能夠說明一切。因此,開發者可能選擇過度承諾,而后因此思路思考架構選擇或者任務自動化等重要議題,旨在滿足不切實際的項目周期要求。這些任務通常被視為附加價值,因此往往會被不假思索地砍掉。產品質量則將隨著技術債務的積累而下降,因為項目后期代碼重組的成本將成倍提升。
舉例來說,我在此項目中發現一部分代碼明顯被到處復制,但看起來開發者同時又急于交付且根本沒時間理會此前是否已經有人編寫過同樣的方法或者SQL查詢。
有時候評估本身還存在誤導性。就如,敏捷性原則中有“速度”這樣一項術語,其思路是計算團隊的交付速度,并作出必要調整以提升速度。問題在于,我們根本不可能立足中、短期給出準確的速度評估結果。平均法則告訴我們,我們無法根據以往的表現來衡量自己未來能夠推進得多快,因為這樣的已知指標并不足以指導未知。
平均法則:小樣本成員間的分布統計結果必須反映在總體成員的分布結果當中。
事實上,一位開發者可能在一天之內編寫大量代碼,也可能在與同事配合的情況下一天只寫出三、五行代碼——其余時間則用于編寫說明文檔及相互溝通。
平均值并不能代表中、短期內的有價值信息凈值。其對于項目而言不具備參考價值。
2.不重視項目相關知識
隨著項目的推進,團隊對于業務、其深層概念以及各元素間的聯系方式亦更為了解。與此同時,各成員亦更為明確如何編寫代碼,這種循序漸進式的認知與問題解決途徑是種必然。某些業務領域甚至存在著固有復雜性,要求開發團隊拿出大量時間進行消化。
這一點在對舊的代碼進行完整重寫方面體現得尤為突出,也反映出您的團隊是否了解項目相關知識。 如果您身處某個大型項目內且其中包含無人了解且無人可以解答的功能模塊,那么結果無疑相當危險。重寫代碼的價值完全取決于您業已掌握的專業知識,因此知識就是力量所言非虛。
如果大家指派另一支隊伍進行重寫,正如我所遇到的情況,則意味著您忽略了原有學習及積累成果,而單純依靠新團隊的自有技能水平。 如果由同一位程序員對自己編寫的原有代碼進行重寫,那么即使其水平平庸亦可帶來更出色的效果及完成速度。在這一點上,利用全新團隊接手絕非良策。
甚至人員招聘工作也與項目知識密切相關。項目負責人掌握的信息越多,其加快項目推進速度的經驗就越豐富,因此除了知識本身的價值之外,這還有助于其招納更為出色的參與人才。如果大家的人員選擇決策不力,那么糟糕的團隊很可能耗時數個月卻一無所獲。
3.關注錯誤的指標取向,例如“已解決問題”或“每天提交數量”
古德哈特法則:當衡量變成目標,其就不再是良好的衡量方式。
在嘗試進行項目提速時,有人問我既然快速交付非常重要,為什么其他開發者能夠比我更快進行代碼提交。然而可以想象,我馬上就從他的一行代碼中找到了四處bug。 專注于代碼提交數量這種不可靠的指標會徹底毀掉整個項目,并使得成員面臨更為巨大的開發周期壓力。
人們普遍忽略了問題回歸率這個問題。像空指針異常這類錯誤往往會在缺少回歸率追蹤的情況下反復出現,并導致整個項目“四處漏風”。在這種情況下,由于著眼點有誤,大家將永遠找不到問題的根源。
最后,真正重要的是我們將怎樣的成果交付給客戶、對方對產品的滿意程度以及成果為其帶來的業務價值,但這要求我們投入大量精力以確保成果質量,而非提交速度或者已解決問題量這類無用的指標。
理想的指標差別方式之一在于了解成員個人的價值觀。注重細節、具備良好的溝通技巧與端正的處理態度非常重要,特別是考慮到如今有很多開發者不惜以欺詐的方式求得所謂效率提升。
4.假設良好的流程能夠彌補個人錯誤
良好的流程雖然極具價值,但其實際效果卻往往受到高估。根據我的個人經驗,相當一部分企業在人才招聘方面處理不當,這迫使其不得不采用越來越嚴苛的執行流程以降低個人錯誤的可能性,而這反過來又限制了團隊的自由創造能力。不僅如此,即使擁有良好的流程,個人因素仍然在其中扮演著重要角色。
這方面追求應當始終得到保持,而良好的招聘機制則能夠在很大程度解決問題。卓越的人才能夠彌補團隊中其它形式的效率低下問題。總體而言,聰明地工作比勤奮地工作更加重要。
開發者往往缺乏良好的溝通能力。在這類復雜的代碼庫中,我需要不斷向他人尋求幫助,但同事們往往沒時間及時伸出援手。他們有時候態度惡劣,而且在提出的問題較為復雜時,幾乎沒有同事具備將其解決的知識與耐心。
我們需要擁有出色知識儲備及良好心態的人員,他們會在進程緩慢時及時發出提醒。 每一款構建工具、每一種靜態檢查工具乃至每一類通訊工具都存在優勢與弊端,大家需要結合各方面意見,而非盲目引入看起來不錯的選項。
5.忽略代碼審查與單元測試等最佳實踐
在現代軟件開發流程當中,保持時間進度已經不足以確保項目處于推進正軌之中,但這至少能夠讓我們的團隊保持競爭力。著眼于最佳實踐指導,測試驅動型開發方法能夠將缺陷率降低40%至90%,而開發時間則僅增加15%到35%代碼審查亦可有效降低缺陷率,有時甚至能夠較手動測試提升80%的錯誤發現比例。
想象一下,在與同事協作時,我只能被迫使用遺留項目加記事本這種上個世紀的處理辦法。因此,使用現代IDE、版本控制以及代碼檢查等功能將有效提升工作效率。 這些并不是什么高新科技,而且必須被應用于各類規模的項目當中。
6.雇用那些完全沒有“人際”技能的開發者
這并不是說開發者就無法與他人交流。我自己也曾經相當害羞內向,但通過強迫性訓練,如今我已經能夠較為順暢地完成溝通甚至演講。
問題在于,當人們壓根不想嘗試溝通或者為此而煩躁時,結果必然極為糟糕。身為開發者,我們必須刻意培養自己的交流能力,甚至將其視為位于開發技能的重要事務。只有這樣,大家才能在工作環境中獲得更為熱情且清晰的意見交換結果。 交流對象身在何處并不重要。一通Skype語音即可將復雜的編碼難題轉變為簡單的五分鐘小問題。
總結
在配合最佳工具、成熟的技能以及卓越的溝通能力之后,軟件開發工作將變得順暢而輕松。 我們不能僅僅因為引入了敏捷性或者其它工具而指望問題瞬間消失,畢竟其僅僅是輔助手段而非包治百病的大力丸。 只要設置得當,它們將建立起協同作用并使團隊的執行效率成倍提升; 然而,如果決策草率及粗暴忽略各種細節,那么項目仍將陷入恐怖的泥潭。