---
# System prepended metadata

title: '[Clean Code]有意義的命名'
tags: [轉職, CleanCode]

---

{%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`