Clean Code: 有意義的命名(Meaningful Names)
Chapter 2: Meaningful names
-
讓名稱代表意圖 (p.20)
變數、函式或類別的名稱,要能解答大部分問題,它應該要告訴你,它為什麼會在這裡出現、它要做什麼用、還有該如何使用它。如果一個名稱還需要註解的輔助,那麼這個名稱就不具備展現意圖的能力。
int d; //消逝的天數
名稱d無法傳達出任何資訊,我們應該選擇能夠具體指明計量及計量單位的名稱:
int elapsedTimeInDays; int daysSinceCreation; int daysSinceModification; int fileAgeInDays;
-
有意義的區別
public static void copyChars(char a1[], char a2[]) { for (int i=0; i < a1.length; i++;) { a2[i] = a1[i]; } }
如果改用source和destination當作參數名稱,這個函式會更容易猜測其意圖。
想像你有一個Product類別,如果又有另一個ProductInfo或ProductData的類別,那只是讓名稱不同而已,無法使它們代表的意義不同。
在沒有特別約定下,變數名稱moneyAmount和money是沒有區別、customerInfo與customer也是沒有區別、accountSata與account、theMessage與message一樣沒有區別。
-
能唸出來的名稱
class DtaRcrd102 { private Date genymdhms; private Date modymdhms; private final String pszqunt = "102"; } class Customer { private Date generationTimestamp; private Date modificationTimestamp; private final String recordId = "102"; }
-
使用可被搜尋的名字
for (int j=0; j<34; j++;) { s += (t[j]*4/5); } int realDaysPerIdealDay = 4; const int WORK_DAYS_PER_WEEK = 5; int sum = 0; for (int j=0; j < NUMBER_OF_TASKS; j++;) { int realTaskDays = taskEstimate[j] * realDaysPerIdealDay; int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK); sum += realTaskWeeks; }
-
避免編碼
成員的字首(Member Prefixes)
void setName(String name) { m_dsc = name; }
-
類別的命名
類別和物件應該使用名詞或名詞片語來命名,例如:Customer、WikiPage、Account
-
方法的命名
方法應該使用動詞或動詞片語來命名,例如:postPayment(登記款項)、deletePage(刪除頁面)、save(儲存)
-
每一種概念使用一種字詞
同一個程式庫裡分別使用了controller(控制器)、manager(管理員)、driver(驅動程式),DeviceManager與ProtocolController的實質差別為何? 這兩個不都是driver的意思嗎? 為何都不改用controller或manager? 這樣的命名會讓你認為是兩個不同類別的物件。
-
別說雙關語
add //新增 insert? append?
-
使用解決方案領域的命名
使用演算法、Pattern名稱
-
使用問題領域的命名
如果沒有程式設計師熟悉的術語可供命名的話,請使用該問題領域的術語來命名
-
添加有意義的上下文資訊
state -> AddrState //如果是要表示為州
處於含糊不清的上下文資訊中的變數
//此函式有些許過長及區域變數幾乎都在整段函式裡被使用 //可將函式分割成更小的函式 private void printGuessStatistics(char candidate, int count) { String number; String verb; String pluralModifier; if (count == 0) { number = "no"; verb = "are"; pluralModifier = "s"; } else if (count == 1) { number = "1"; verb = "is"; pluralModifier = ""; } else { number = Integer.toString(count); verb = "are"; pluralModifier = "s"; } String guessMessage = String.format( "There %s %s %s%s", verb, number, candidate, pluralModifier ); print(guessMessage); }
處於上下文資訊中的變數
public class GuessStatisticsMessage() { private String number; private String verb; private String pluralModifier; public String make(char candidate, int count) { createPluralDependentMessageParts(count); return String.format("There %s %s %s%s", verb, number, candidate, pluralModifier); } private void createPluralDependentMessageParts(int count) { if (count == 0) { thereAreNoLetters(); } else if (count == 1) { thereIsOneLetter(); } else { thereAreManyLetters(count); } } private void thereAreManyLetters(int count) { number = Integer.toString(count); verb = "are"; pluralModifier = "s"; } private void thereIsOneLetter(int count) { number = "1"; verb = "is"; pluralModifier = ""; } private void thereAreNoLetters(int count) { number = "no"; verb = "are"; pluralModifier = "s"; } }