工程實踐:給函式取一個"好"的名字
早在2013年,國外有個程式員做了一個有意思的投票統計(原始鏈接請見:《程式員:你認為最難做的事情是什么?》),該投票是讓程式員從以下幾個選項中選出平時在作業中自己認為最難做的事情:
- 做專案方案設計
- 撰寫測驗用例
- 撰寫設計檔案
- 向別人解釋我們在做什么事情
- 實作你不認同的feature
- 在別人寫的代碼基礎上做改造
- 與人溝通
- 給函式、變數命名
- 進行作業量估時
也許在大家的印象中,撰寫設計檔案和在別人寫的代碼基礎上做改造應該是最難的事情,但是最終的投票結果確讓大家意想不到,這次投票一起有4522名程式員參與了投票,排在第一位的是給函式、變數命名:

大概一半的人投票給了給函式、變數命名,從這次投票結果我們足可以看出:給函式、變數命名雖然是一件再普通不過的事情,但是要想把這件事做好絕非易事,那么今天,我們就來聊一聊如何給函式取一個好的名字,以下是本文大綱目錄:
一.常見的函式命名風格
二.函式命名的最高境界
三.函式命名最佳實踐
若有不正之處請多多諒解,并歡迎批評指正,
請尊重作者勞動成果,轉載請標明原文鏈接:
https://www.cnblogs.com/dolphin0520/p/10567879.html
一.常見函式命名風格
目前來說,最常見的函式命名主要有兩種風格:駝峰命名和帕斯卡命名,
- 駝峰命名:多個單詞組成一個名稱時,第一個單詞全部小寫,后面單詞首字母大寫;如:
public void setUserName(String userName);
- 帕斯卡命名:多個單詞組成一個名稱時,每個單詞的首字母大寫;
public void SetUserName(String userName);
兩種命名風格都是ok的,但要保證一點,對于一個團隊或者一個專案,需要根據語言本身的推薦命名方式做好約定,比如java一般都采取駝峰命名,C#采取帕斯卡命名,
二. 函式命名最高境界
我們通常說:天下武功,唯快不破,那么對于函式命名來說最高境界是什么呢?我認為是:見字如面,顧名思義,就是看到函式的名字就知道這個函式具體做了哪些事情,
比如上面的函式:
public void setUserName(String userName);
但是下面這個函式命名就不是一個好的命名:
public String addCharacter(String originString, char ch);
這個函式,一咋看,還不錯,從函式字面意思看是給某個字串添加一個字符,但是到底是在原有字串首部添加,還是在原有字串末尾追加呢?亦或是在某個固定位置插入呢?從函式名字完全看不出來這個函式的真正意圖,只能繼續往下讀這個函式的具體實作才知道,
而下面這幾個名字就比上面要好得多:
public String appendCharacter(String originString, char ch); // 追加到末尾 public String insertCharacter(String originString, char ch, int insertPosition); // 插入指定位置
三. 函式命名最佳實踐
1)要領1:動詞選取要精準
通常來說,動詞決定了一個函式要采取什么"動作",動詞取的好,一個函式名字已經成功了80%,
常用動詞表:
| 類別 | 單詞 |
| 添加/插入/創建/初始化/加載 | add、append、insert、create、initialize、load |
| 洗掉/銷毀 | delete、remove、destroy、drop |
| 打開/開始/啟動 | open、start |
| 關閉/停止 | close、stop |
| 獲取/讀取/查找/查詢 | get、fetch、acquire、read、search、find、query |
| 設定/重置/放入/寫入/釋放/重繪 | set、reset、put、write、release、refresh |
| 發送/推送 | send、push |
| 接收/拉取 | receive、pull |
| 提交/撤銷/取消 | submit、cancel |
| 收集/采集/選取/選擇 | collect、pick、select |
| 提取/決議 | sub、extract、parse |
| 編碼/解碼 | encode、decode |
| 填充/打包/壓縮 | fill、pack、compress |
| 清空/拆包/解壓 | flush、clear、unpack、decompress |
| 增加/減少 | increase、decrease、reduce |
| 分隔/拼接 | split、join、concat |
| 過濾/校驗/檢測 | filter、valid、check |
動詞決定了函式的具體動作,而名詞決定了函式具體的操作物件,對于名詞,盡量使用領域詞匯,不要使用生僻或者大家很少使用的詞語,
2)要領2:名詞使用領域詞匯
舉個例子:集合的容量通常用capacity、集合實際元素個數用size、字串長度用length,這種就遵循大家的使用習慣,不要用size去形如字串的長度,
再比如,假如使用到建造者模式,那么通常會用build作為函式名字,這個時候就不要另辟蹊徑,用create來作為函式名字,使用大家約定俗成的命名習慣更容易讓你的代碼被別人讀懂,
常用名詞表:
| 類別 | 單詞 |
| 容量/大小/長度 | capacity、size、length |
| 實體/背景關系 | instance、context |
| 配置 | config、settings |
| 頭部/前面/前一個/第一個 | header、front、previous、first |
| 尾部/后面/后一個/最后一個 | tail、back、next、last |
| 區間/區域/某一部分/范圍/規模 | range、interval、region、area、section、scope、scale |
| 快取/緩沖/會話 | cache、buffer、session |
| 本地/區域/全域 | local、global |
| 成員/元素 | member、element |
| 選單/串列 | menu、list |
| 源/目標 | source、destination、target |
3)要領3:函式取名最忌諱"名不副實"
函式取名最忌諱的是"名不副實",舉個例子,假如有個Cache類,里面有個函式判斷key是否過期:
public boolean isExpired(String key) {
// 當前時間戳
long curTimestamp = DateUtils.nowUnixTime();
// 獲取key的存入時間戳
long storeTimestamp = getStoreTimestamp(key);
if (curTimestamp - storeTimestamp > MAX_EXPIRE_SECONDS) {
// 注意這個地方的delete是個隱藏邏輯
delete(key);
return true;
}
return false;
}
上面這個函式從函式字面意思看是判斷key是否過期,但是!!它居然在函式里面隱藏了一段特殊邏輯:如果過期則洗掉掉key,這個就是典型的"名不副實",這個是最忌諱的,會給后續的開發人員留下"巨坑",
有兩種方式去優化這段代碼:
- 方式一:將隱藏邏輯去掉
public boolean isExpired(String key) {
// 當前時間戳
long curTimestamp = DateUtils.nowUnixTime();
// 獲取key的存入時間戳
long storeTimestamp = getStoreTimestamp(key);
if (curTimestamp - storeTimestamp > MAX_EXPIRE_SECONDS) {
return true;
}
return false;
}
- 方式二:改變函式名字
public int deleteIfExpired(String key) {
// 當前時間戳
long curTimestamp = DateUtils.nowUnixTime();
// 獲取key的存入時間戳
long storeTimestamp = getStoreTimestamp(key);
if (curTimestamp - storeTimestamp > MAX_EXPIRE_SECONDS) {
return delete(key);
}
return 0;
}
4)要領4:多查詢條件的函式名字謹慎使用介詞by
我們平時在寫查詢介面時,假如有多個查詢引數怎么辦?每個通過by一起連接依賴?No!這絕對不是明智的方式,假如一開始產品的需求是通過學生姓名查詢學生資訊,寫出來的可能是這樣的函式:
public List<Student> getByName(String name);
然后突然又有一天產品提出了新的需求,希望同時可以通過姓名和電話號碼來查詢學生資訊,那么函式可能變成這樣了:
public List<Student> getByNameAndMobile(String name, String mobile);
接著,沒過多久,產品又希望根據學生年齡來查詢學生資訊,那么函式可能變成這樣了:
public List<Student> getByNameAndMobileAndAge(String name, String mobile, int age);
如果這樣來給函式命名,那么你的噩夢大門即將打開,
通常比較好的做法是:
-
如果是通過主鍵id來查詢,那么可以通過by來連接查詢資訊,比如:
public Student getByStudentId(long studentId);
-
如果是通過其他屬性來查詢,并且未來會存在多個組合查詢的可能性,建議進行封裝,比如:
public List<Student> getStudents(StudentSearchParam searchParam);
最后,建議大家平時在寫代碼程序中,不要怕在函式命名上耗費時間,一個好的函式命名在后期會大大減少你代碼重構的成本,爭取對函式命名做到"見字如面"~
推薦下海子剛開通的微信公眾號,歡迎大家掃碼關注:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/214884.html
標籤:其他
上一篇:解決CRT界面漢字亂碼問題
