@Kais(VagrantPi)
slide
, 簡報
, Clean Code
int d; // elapsed time in days
int elapsedTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
// theList 代表什麼?
for (int[] x : theList)
// x[0] 代表什麼?
// 4 代表什麼?
if (x[0] == 4)
list1.add(x);
return list1;
}
看得出來這邊會遍歷 gameBoard,如果 cell 的狀態碼為 FLAGGED,則會加到已標記(flaggedCells)list 中
- public List<int[]> getThem() {
+ public List<int[]> getFlaggedCells() {
- List<int[]> list1 = new ArrayList<int[]>();
+ List<int[]> flaggedCells = new ArrayList<int[]>();
- for (int[] x : theList)
+ for (int[] cell : gameBoard)
- if (x[0] == 4)
+ if (cell[STATUS_VALUE] == FLAGGED)
- list1.add(x);
+ flaggedCells.add(cell);
- return list1;
+ return flaggedCells;
}
這邊使用泛型進一步抽象化
- public List<int[]> getFlaggedCells() {
+ public List<Cell> getFlaggedCells() {
- List<int[]> flaggedCells = new ArrayList<int[]>();
+ List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard)
- if (cell[STATUS_VALUE] == FLAGGED)
+ if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
另外這些命名也與一些系統平台或指令撞名
Handling
OfStringsStorage
OfStrings- public static void copyChars(char a1[], char a2[]) {
+ public static void copyChars(source a1[], destination a2[]) {
for (int i = 0; i < a1.length; i++) {
a2[i] = a1[i];
}
}
a
、an
、the
Data
與 Info
之類的用詞也是無意義的,舉例 ProductData
、ProductInfo
同樣代表 Product 類別的資料,但兩者差異只在於命名不同,幾乎等價於 Product
常見縮寫併再一起幾乎唸不出來
genymdhms (generation date, year, month, day, hour, minute,
and second)
都念不出來了,更難想像意圖,因此沒有文件下,後續接手的同人無法維護
應該可以簡單判斷哪個比較好讀
class DtaRcrd102 {
private Date genymdhms;
private Date modymdhms;
private final String pszqint = "102";
/* ... */
};
class Customer {
private Date generationTimestamp;
private Date modificationTimestamp;;
private final String recordId = "102";
/* ... */
};
長命名勝於短命名
常數命名會避數字容易被搜尋
const int WORK_DAYS_PER_WEEK = 5;
比較要在整個專案中搜尋到 5,WORK_DAYS_PER_WEEK
會更好找到
IShapeFactory
更傾向使用 ShapeFactory
,而如果一定要對 Interface、Implementations 進行命名,這樣這邊會建議只對 Implementations 命名。ShapeFactoryImp
都比在 interface 在前面加個 I 好i
、j
、k
這類變數,使用在 for 迴圈內可說是約定熟成
但單個字當變數在其他地方,可以說是非常糟糕,還需要在腦內轉換一下,才能對應到真實的變數概念
『清楚才是王道』
class 的命名應該為名詞與名詞片語
方法應該是用動詞或是動詞片語
此外,在 Javabean 的標準中
HolyHandGrenade(神聖手榴彈),光看名字不知道這個 Method 要做什麼,娛樂價值大於實用
原先有一個 add 方法用來做『相加或想連』的概念,散落多個 class 中,今天有一個新類別也用了這個 add,但是功能卻將參數『加』進物件內。因此這出現了一個命名兩個意思的問題,這邊可能使用 insert 或是 append 會更好些
使用工程師的電腦科學專業術語、演算法名稱、pattern name、數學字彙協助命名
因為讀你程式碼的,也會是工程師
可以詢問問題領域專家使用的術語來幫助命名
變數時常需要搭配上下文,來盼端該變數實際的意義
如果只看到變數 state ,你會聯想到什麼
那看到 street, houseNumber, city, state, zipcode 你應該猜得出來這個 state 是什麼了
當然,如果將這些全部幫進 Address 的 class 會更清楚
以下有另外一個例子
// 統計猜測
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() {
number = "1";
verb = "is";
pluralModifier = "";
}
private void thereAreNoLetters() {
number = "no";
verb = "are";
pluralModifier = "s";
}
}
假設有個系統『豪華版加油站(Gas Station Deluxe)』
因此在每個 Class 前都加上 GSD 字首,這很明顯在跟 IDE 做對,因為當輸入 G
後,會跳出系統哪所影類別的建議
此外,如果較小的命名可以清楚表達,則好過較長命名,以免添加過多與內文不符的名稱
public class Address {
private String accountAddress; // 帳戶地址
private String customerAddress; // 客戶地址
}
accountAddress
、customerAddress
是個明確的命名
需要良好的描述技巧,與共同的文化背景,