手把手教你應對這 15 種「爛程式碼」

  • 2019 年 11 月 27 日
  • 筆記

閱讀本文大概需要 4.5 分鐘。

編譯:AI開發者-McDonald s,作者:Jun Wu

如果你不能辨認出這些「爛程式碼」,你根本不可能把bug修復好。

想像一下以下場景:

你已經在某個項目的一部分中拖延了很久。

推遲了一周以後,今天是你計劃打開遺留程式碼庫並查看已完成的內容的時候。你一想到這程式碼庫就害怕。

因為你知道離岸軟體開發團隊已經接觸了多年這些程式碼,而且這些程式碼已經有五年的歷史了。

你還知道讓你接手這些程式碼就是讓你去改進它們的。由於預算問題,管理層決定「重用」程式碼,而不是放棄整個項目。

現在,你身處國外,你希望在另一邊等待你的是「好程式碼」,但是又非常清楚這些程式碼有95%的概率是「爛程式碼」。

你用一大杯咖啡開始一天的生活,讓(修復這些程式碼的)這個過程不那麼痛苦。因為在幾分鐘內,你就會接觸到一個非常糟糕的程式碼示例。

亂得像義大利面一樣的程式碼 — by Jun Wu

這些程式碼不僅亂得像你家三歲小孩剛畫的畫,還有點像他喜歡的食物一樣。

確定了這些程式碼到底有多爛以後,你可以向管理層再次重申這些程式碼的修復時長是重寫程式碼所需時長的兩倍。

1. 無法訪問的程式碼

如果不改變邏輯,那麼這段程式碼將永遠無法訪問。

示例:

function {} {  return x;  z=a+b;  }

修復措施:刪掉它們

2. 包括冗餘類的無用程式碼

這一類的程式碼完全就是多餘的,或者根本就沒有任何作用。

示例:

function() {  a+b;  }  or  function() {  c=a+b;  c=a;  c=b+c;  }

修復措施:要麼重寫程式碼,要麼刪掉。

3. 過於龐大的類

如果這個類花了20分鐘才找到其中的邏輯,那你還留著它幹什麼?(趕緊刪了吧!)這都有多少行程式碼了,長得像一章小說一樣。

修復措施:請趕緊重構!

4. 循環引用導致產生上帝對象

這類程式碼似乎很快就會回到相同的目標。這將會導致 上帝對象 (https://en.wikipedia.org/wiki/God_object)的產生,一個「了解過多或負責過多」的對象。這也是反模式的一個例子。

圖片來自 Wikipedia

修復措施:重構程式碼,或者設計並將它們分成獨立的分組。

5. 投機性的程式碼

有人寫這些程式碼僅僅是為了防止某些將來可能出現(但從來沒有發生過的)的情況發生。

修復措施:刪了吧,別留了。

6. 硬編碼

這類程式碼是最容易發現和預防的。因為在每次修改值的時候,都必須修改程式碼。

這類硬編碼也被認為是一種反模式。一般情況下,在項目釋放資源以添加一個允許用戶輸入值的動態解決方案之前,會暫時執行這個操作。

修復措施:創建一個該動態的介面允許修改值。

7. 神奇的數字

就是一個直接使用的數字,你也不知道為什麼是它。

示例:

function(){  for(int i=0; i<10; i++)  {    }    }

在上面的示例中,10 就是那個神奇的數字。

修復措施:用 數值10 來初始化的變數 替換掉這個固定值 10.

8. 冗長的如果(條件)

以下是一個非常長的 if 語句的邏輯,不同的行僅用於簡單地容納這些邏輯。

if(get_data(data)=success || (reuse(data)&&cut_data(data)==success)||(reuse_again(data) && cut_data(data)==success))

解決辦法:用特定的程式語言樣式對這類冗長的 if(條件)語句進行格式化。

9. 順序耦合

也就是說,必須要按照特定順序才能調用的方法。舉個例子,假設你有一個「begin」的方法,你必須要在「start」方法之前調用它,然後才能調用「drive」方法。

修復措施:請使用設計模式裡面的「模板方法模式」。

10. 過度使用繼承方法

面向對象編程中過多的繼承將會導致程式碼緊密耦合且不靈活。然而,你可以把注意力放在組成上。

neethack.com(http://neethack.com/2017/04/Why-inheritance-is-bad/)上有一個很好的例子和解決方法,可移步查看。

11. 不使用核心程式語言的功能

這一點不是非常明顯。但是,為了這個項目而選擇某種程式語言是有原因的。Python中的一個很好的例子就是使用循環來處理簡單的任務,而不是使用列表理解。

12. 過度複雜的注釋

如果你的注釋在一段非常大的程式碼塊中,或者過於複雜,這有可能是一個警告訊號,說明了這段程式碼也需要重構。

修復措施:通過提取方法或變數來重構。

13. 消息鏈

消息鏈就像老師跟幼兒A說話,幼兒A和幼兒B說話一樣。老師就是客戶端,幼兒是消息鏈中的對象。而這裡的問題是,這條消息鏈上任何關係的更改都需要對客戶端進行更改。

修復措施:通過隱藏委託進行重構。

14. 數據塊

這裡指的是程式碼的不同部分包含了相同的變數組。其中一個典型的例子是,當你在程式碼中多次連接到服務的參數時,就會發現這個數據塊。

修復措施:通過創建一個新的參數對象或者提取類來重構。

15. Poltergeists

這些類在系統中扮演的角色有限,本質上只是使得軟體變得更加混亂。它們有可能是臨時關聯、無狀態類、臨時對象和類,以及冗餘指向。

修復措施:通過將原本在poltergeist中的動作移動到它們調用的相關類中來重構。

結語

我已經詳細介紹了15種不同的方法來發現這些「爛程式碼」,現在是時候通過定義「什麼是好程式碼」來結束本文了。

圖片來自:@safesolvent unsplash.com

  • 良好的程式碼應當具有良好的組織、良好的測試、簡單且直觀。
  • 良好的程式碼應該是非常優雅的,因此可以非常輕鬆地向學齡兒童解釋其中的邏輯。
  • 任何人都能寫出一手好程式碼,你的程式設計師不必成為火箭科學家也能寫出好程式碼。
  • 最重要的是,良好的程式碼將長久保留、生生不息。

如果你還沒有讀過《 Clean Code: A Handbook of Agile Software Craftsmanship (整理程式碼:敏捷軟體的製程手冊)》這本書,建議你去讀一讀:https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882。

良好的程式碼只需要幾個簡單的修復。你還在等什麼?