Clean Code: A Handbook of Agile Software Craftsmanship
看書名就知道這是一本教你怎麼寫出乾淨又簡潔的code
書中提的一些概念和方法我覺得蠻有用的,很推薦大家去看這本書
以下是我整理的一些筆記
- Use Intention-Revealing Names
- 選一個好的變數名稱雖然會花時間,但是未來絕對可以幫你省下更多時間
- 一個好的命名要能傳達以下資訊
- Why it exists?
- What it does?
- How it is used?
- 需要額外的註解,不是好的命名
int d; // elapsed time in days好的命名,清楚的表達變數的用途 int elapsedTimeInDays; int daysSinceCreation; int daysSinceModification; int fileAgeInDays;
- 不好的命名方式,很難看懂這段code在做什麽
public List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>(); for (int[] x : theList) if (x[0] == 4) list1.add(x); return list1; }同樣一段code經過重新命名後可以看出這是一段踩地雷遊戲程式 public List<int[]> getFlaggedCells() { List<int[]> flaggedCells = new ArrayList<int[]>(); for (int[] cell : gameBoard) if (cell[STATUS_VALUE] == FLAGGED) flaggedCells.add(cell); return flaggedCells; }更好的作法,用一個Cell的class來取代array of ints public List<int[]> getFlaggedCells() { List<int[]> flaggedCells = new ArrayList<int[]>(); for (Cell cell : gameBoard) if (cell.isFlagged()) flaggedCells.add(cell); return flaggedCells; }
- Avoid Disinformation
- 不要使用一些特殊縮寫的名字
- ex: hp, aix , sco (這些縮寫在Unix有特殊意義)
- 不要使用accountList ,除非他真的是一個List
- 就算真的是List也不要把Type encoding到命名裡
- accountGroup, bunchOfAccounts, 或是只用accounts都會比accountList來的好
- 命名不要太過相似
- XYZMyTodayBrunchBread 和 XYZMyTodayBreakfastBread 很難被區別
- 不要使用小寫L和小寫O來做命名,因為很難跟1和0做區別
int a = l; if ( O == l ) a = O1; else l = 01;
- 命名要有意義上的區別
- 使用Number-series naming(a1, a2, .. aN)不是一種好的命名方式
public static void copyChars(char a1[], char a2[]) { for (int i = 0; i < a1.length; i++) { a2[i] = a1[i]; } }
- ex: Product, ProductInfo, ProductData,你無法分辨這三者有什麽不同
- ex: NameString, CustomerObject,難道Name會是一個floating pointer嗎?
getActiveAccount(); getActiveAccounts(); getActiveAccountInfo();
- 使用可以發音的單字來命名,方便Programmer之間溝通
- genymdhms(generation date, year, month, day, hour, minute, and second)應改成 generationTimestamp
- 使用好被搜尋的名字
- MAX_CLASSES_PER_STUDENT會比數字7要來的好被找到(簡單說就是不要用magic number)
- single-letter命名只能被使用在short methods中的local variable
- 不要使用匈牙利命名法
- 早期因為Compiler不會幫忙檢查type才需要匈牙利命名法,現在的Compiler都很強大
- 使用匈牙利命名法未來如果要更動型別會很麻煩
PhoneNumber phoneString; // name not changed when type changed!
- Member Prefixes
- 不需要prefix member variable with m_
- 直接用this pointer來區分會比較好,而且在大多數的編輯器中this會有highlight
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; } }
- 不要使用單一小寫字母來做命名,因為會需要人腦去做Mapping
- 如果在很小並且不會和其他名稱衝突的scope,比如說迴圈,使用i, j, k還可以被接受。因為大家都習慣了,容易聯想
- 如果是使用單一字母a, b, c的話就很糟糕
- 清楚命名才是王道(clarity is king)
- 使用名詞來命名Class和Object,不要使用動詞
- ex: Customer, WikiPage, Account, AddressParser
- 避免使用Manager, Processor, Data, Info
- 使用動詞來命名,ex: postPayment, deletePage, save
- Accessors, mutators和predicates要以 get, set和is開頭
string name = employee.getName(); customer.setName("Mike"); if (paycheck.isPosted())...
- 不要使用俚語或是隱喻的命名方式,因為別人有可能會看不懂
- (X)HolyHandGrenade => (O)DeleteItems
- (X)whack() => (O)kill()
- (X)eatMyShorts() => (O)abort()
- 使用一樣的單字來表達同樣一件事情
- 沒有人分的出來fetch, retrieve, get有什麽差別,使用其中一個為你的method命名就好
- DeviceManager和ProtocolController,看到這兩個單字你會疑惑Manager和Controller有什麽差別。因此不是一個好的命名
- 維持code的一致性是很重要的
- 不要使用同一個單字去表達兩個不同的概念
- 如果已經有一個叫做add的method用來把兩數相加,就要避免再用add命名"把single parameter加到一個collection的method"。改用insert和append
- 命名盡量使用Computer Science領域的專有名詞,因為讀你code的人都是programmer
- 好的例子
- AccountVisitor => VISITOR pattern
- JobQueue => 每個programmer都知道這是什麽
- 如果沒有Solution Domain Names可以使用,那就使用和你所解問題有關的字彙。至少可以讓看你code的人去問相關領域的專家
- firstName, lastName, street, houseNumber, city, state, zipcode這些變數放在一起很明顯可以組成一個address。但是如果你只看到state,你會不知道這代表什麽意思
- 使用prefix讓他們組合成一個概念,addrFirstName, addrLastName, addrState......
- 不要加上多餘的prefix
- 如果一個application叫做"Gas Satation Deluxe",不需要把所有的class都加上GSD這個prefix
- 會很難使用IDE做搜尋(所有Class開頭都是GSD)
- Class名稱會變的很冗長
- 不要害怕重新命名,現在有很多好用的tool可以幫助你
沒有留言:
張貼留言