命名的藝術(clean code閱讀筆記之一)

本文是「Clean Code」(英文版)第二章的讀書筆記。

第二章簡單地列舉了一些命名規則,我們在coding的時候會不斷地對我們的變量、函數、參數、類、package,甚至源文件、和包含源文件的目錄等等進行命名,這里是簡單的幾個命名規則能幫助你更好地對這些命名。

1. 使用名副其實(Intention-Revealing)的名字

  • 不要定義無意義的名字

  • 不要使用magic numbers

  • 例子:

      // 壞代碼例子
      public List<int[]> getThem() {
          List<int[]> list1 = new ArrayList<int[]>(); 
          for (int[] x : theList)
              if (x[0] == 4) list1.add(x);
          return list1; 
      }
    
      //不是很壞的代碼
      public List<int[]> getFlaggedCells() {
          List<int[]> flaggedCells = new ArrayList<int[]>();
          for (int[] cell : gameBoard)
              if (cell[STATUS_VALUE] == FLAGGED) 
                  flaggedCells.add(cell);
          return flaggedCells;
      }
    
      //好代碼
      public List<Cell> getFlaggedCells() {
          List<Cell> flaggedCells = new ArrayList<Cell>();
          for (Cell cell : gameBoard) 
              if (cell.isFlagged())
                  flaggedCells.add(cell); 
          return flaggedCells;
      }
    

2. 避免傳達錯誤的意思

  • 避免使用有歧義的名字,比如與其他已存的命名系統相同或相似的名字(比如hp, aix, sco)

  • 避免使用與語言特性相關的詞,比如,accountList, 如果它真的是一個某些語言中的List結構還好,如果不是,最好使用bunchOfAccounts或者直接accounts更好。

  • 避免在不同的地方使用只有微妙區別的命名。比如你要花多久才能區分一下兩個變量:

      XYZControllerForEfficientHandlingOfStrings
      XYZControllerForEfficientStorageOfStrings
    
  • 使用相似的命名來代表相似的概念。這一條和上一條并不沖突,相似的概念應該使用相似但可以有明顯的區分度的命名進行表達。

  • 避免使用外形上很容易造成誤解的命名:比如大寫的o和小寫的L,它們和0和1特別像,很難區分。

3. 在命名和命名之間使用有意義的區別

  • 比如:在一段代碼中如果需要使用兩個相似概念的變量時,盡量使用有意義的方式來區別它們,避免使用a1、a2等變量命名。

  • 避免使用不必要的“噪音字”。一個類名叫Product比叫ProductInfo或者ProductData等好多了。

  • 避免使用冗余的’噪音字’。變量名中永遠不應該包含單詞variable;表名中應當永遠不包含table。

  • 這里是一個錯誤的示例,這三個函數的命名完全是沒有意義的

      getActiveAccount(); 
      getActiveAccounts(); 
      getActiveAccountInfo();
    

4. 使用語音可讀的命名

  • 一個好的命名應該是可讀的,可讀的命名能幫助人更好理解代碼,同時使人們更容易去討論這些代碼。
  • 盡量避免使用genymdhms(generation date,year, month,打野,后人,minute,and second)這樣很難讀出來的命名,而使用generationTimeStamp

5. 使用容易搜索的命名

  • 這條其實還是說要使用有意義的命名,比如一個變量MAX_CLASSES_PER_STUDENT是7,就不要把這個變量的名字定 義為SEVEN,這樣更方便程序的讀者去搜索。

  • 作者在這里寫道,單個字母的變量名(i, j, k等)應該只能作為一個很短的方法的內部變量使用。

6. 避免發明新的編碼方式來命名

  • 匈牙利命名法:由于現代語言對于命名的長度已經沒有限制,所以像匈牙利命名法這種對命名進行二次編碼的方式應該盡量避免使用

  • 前綴:很多語言使用前綴m_來標識這個變量是一個成員變量,這種做法是沒有意義的,程序的讀者經常會無視你的前綴而只關注后邊的內容。另外,你的類和方法的定義范圍應該足夠小,讓你不需要使用這一的前綴

      public class Part {
          private String m_dsc; // The textual description void setName(String name) {
              m_dsc = name; 
          }
      } 
    
      public class Part {
          String description;
          void setDescription(String description) {
              this.description = description; 
          }
      }
    
  • 接口和實現的命名:作者建議接口名盡量不要使用前綴,比如IShapeFactory作為接口,ShapeFactory作為實現類。應該避免讓這個接口的使用者看到給他使用的是一個接口。

7. 避免腦補

  • 避免寫出晦澀難懂的命名,比如在某處定義一個變量名為r,而只有寫代碼的人知道這個r代表的是url的小寫形式。
  • 類名:類名應當是一個名詞或名詞短語,而不是動詞
  • 方法名:方法名應當是一個動詞短語;當構造器需要重載時,盡量使用不同命名的工廠方法,而不是使用重載的不同參數的構造器(這點我是持保留意見的)。

8. 不要使用可愛的命名

9. 同一個概念使用同一個單詞

  • 避免在一個工程中使用fetch、get、retrieve等相似的單詞來表達相同的意思。
  • 相同的,還有經常使用到的Manager、Controller、Driver等。

10. 避免使用雙關語

  • 同一個單詞在兩個不同的場景下被使用,往往會造成誤解,尤其是這兩種場景下它們的意思還是不相同的。

11. 使用程序員熟悉的專有名詞

  • 不要害怕使用一些專有的計算機名詞,比如算法,設計模式,數學名詞等等。

12. 使用描述問題的命名

  • 如果沒有一個計算機專業名詞來描述你的方法或者變量,盡量保證你的命名可以清晰描述你的問題。

13. 添加有意義的上下文

  • 寫程序就像寫文章,每一個方法或者類都像一個段落,一些命名他們本身并沒有很明顯的含義,那么就需要把它放在一個有意義的上下文中,比如一個地址類Address,里邊有一個屬性是state,就明顯是標識州的意思,但是在別的上下文可能會有不同的含義。

14. 不要添加無意義的上下文

  • 作者建議盡可能使用短的名字(在能清晰表達它意思的前提下)
  • 作者在這里舉的無意義的上下文的例子有:在一個名為“Gas Station Deluxe”的程序中,所有的類都加上GSD的前綴,這樣的上下文是無意義的(這里讓我想到了Objective-C的GCD,哈哈)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容