{%hackmd BJzAwtWvp %} # [Clean Code]有意義的命名 ## 讓名稱代表意圖-使之名副其實 * 變數、函示與類別的名稱,要能解答大部分的問題。他需要告訴你,他為什麼在這出現、他要做甚麼、要怎麼使用他。如果一個名稱還需要註解的輔助,那麼這個名稱就不具備展現意圖的能力。 以下的範例就看不出這個變數的命名意義為何,還需要一個註解幫他解釋。 ``` int d; //消逝的天數 int daysSinceCreatio int daysSinceCreatio數值4n; int daysSinceModification; ``` * 我們以一段程式碼作為範例來點出我們需要哪些資訊 ``` public List<int[]> getThem(){ List<int[]> list1 = new ArrayList<int[]>(); for(int[] x : theList){ if(x[0] == 4){ list1.add(x); } } return list1; } ``` 1. theList裡存著甚麼東西? 2. theList裡索引0的項目,代表的意義是甚麼? 3. 數值4是甚麼意思? 4. 我該如何使用回傳的列表? 這些問題都沒有在程式碼中透漏,但它們應該要辦到這件事情。 我們假設這段程式碼是在編寫踩地雷的遊戲,並把他改寫為如下 ``` public List<int[]> getFlaggedCells(){ List<int[]> flaggedCells = new ArrayList<int[]>(); for(int[] cell : gameBoard){ if(cell[STATUS_VALUE] == FLAGGED){ flaggedCells.add(cell); } } return flaggedCells; } ``` 如此一來,此段程式碼的意圖就非常明確。 另外我們還可以透過簡單的類別宣告取代int[],使之更為明確。 ``` public List<Cell> getFlaggedCells(){ List<Cell> flaggedCells = new ArrayList<cell>(); for(Cell cell : gameBoard){ if(cell.isFlagged){ flaggedCells.add(cell); } } return flaggedCells; } ``` ## 避免誤導 ## 產生有意義的差別 * 如 a 及 the ``` private String aBook; private String theBook; ``` 這樣的命名方式無法看出兩者的不同。 ## 使用能唸出來的名稱 * 這裡提供一個範例,以下這個function是做甚麼的,你能看的出來嗎? ``` public String genymdhms(); ``` 這個方法是拿來產生年月日時分秒的,但是由這樣的命名方式看起來非常地不直觀。 ## 使用可被搜尋的名字 * 這樣在debug及察看是否有相同命名的狀況時,可以加快尋找及解決的速度。 ## 不要使用編碼當作命名 * 編碼已經很多了啦!!不要再出來亂了!! * 這樣的命名方式,必須確保所有的觀看成員都能理解這種編碼,但實際上這樣是不可能的。 ## 成員的自首 * 盡量避免在變數的前面加上如下這種幫助理解的自首 ``` private object m_info; ``` 而是利用建立物件或是周全周遭的命名來提升它的可讀性。 ``` private Member info; ``` ## 避免思維轉換 ## 類別的命名 * 類別和物件的命名應該使用名詞或名詞片語來命名,不應該使用動詞 ## 方法的命名 * 應該使用動詞或動詞片語作為開頭,並盡量依照javaBean的標準(get、set、is)。 * 當建構子被多載時 這樣寫 ``` Complex fulcurmPoint = Complex.FromRealNumber(23.0); ``` 會比這樣寫來的好 ``` Complex fulcurmPoint = new Complex(23.0); ``` 因為這樣也可以明確的了解是由甚麼樣的情境下產生這個物件。 也建議可考慮強制將對應的建構子都這為私有的private。 ## 不要裝可愛 ``` private void deleteAccount(String accountId); X private coid holyHandGrenade(String accountId); √ ``` ## 使用同一種字詞 * 如取得資料時,使用了三種不同的"取得"動詞作為開頭,一方面無法確定功能是否相同,一方面在搜尋時也無法搜出確切需要的資料。 ``` private String getName(); private String retrieveName(); private String fetchName(); ``` ## 添加有意義的上下文資訊 * 以下這樣的命名你會不知道是甚麼的名字、甚麼的號碼 ``` private String name; private String number; ``` 但若改為以下這樣便能清楚了解是使用者的名字、使用者的手機號碼。 ``` prviate String userName; private String userMobileNumber ``` 當然,若是可以為次建立一個物件,那會是更好的解法。 --- - 資料來源 - Clean code 無瑕的程式碼 --- ###### tags: `cleanCode`