函數如何命名


原文鏈接:https://www.cnblogs.com/dolphin0520/p/10567879.html

一.常見函數命名風格

  目前來說,最常見的函數命名主要有兩種風格:駝峰命名和帕斯卡命名。

  • 駝峰命名:多個單詞組成一個名稱時,第一個單詞全部小寫,后面單詞首字母大寫;如:
1
public  void  setUserName(String userName);
  • 帕斯卡命名:多個單詞組成一個名稱時,每個單詞的首字母大寫;
1
public  void  SetUserName(String userName);

  兩種命名風格都是ok的,但要保證一點,對於一個團隊或者一個項目,需要根據語言本身的推薦命名方式做好約定。比如java一般都采取駝峰命名,C#采取帕斯卡命名。

二. 函數命名最高境界

  我們通常說:天下武功,唯快不破。那么對於函數命名來說最高境界是什么呢?我認為是:見字如面,顧名思義,就是看到函數的名字就知道這個函數具體做了哪些事情。

  比如上面的函數:

1
public  void  setUserName(String userName);

  但是下面這個函數命名就不是一個好的命名:

1
public  String addCharacter(String originString,  char  ch);

  這個函數,一咋看,還不錯,從函數字面意思看是給某個字符串添加一個字符。但是到底是在原有字符串首部添加,還是在原有字符串末尾追加呢?亦或是在某個固定位置插入呢?從函數名字完全看不出來這個函數的真正意圖,只能繼續往下讀這個函數的具體實現才知道。

  而下面這幾個名字就比上面要好得多:

1
2
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是否過期:

1
2
3
4
5
6
7
8
9
10
11
12
13
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。這個就是典型的"名不副實",這個是最忌諱的,會給后續的開發人員留下"巨坑"。

  有兩種方式去優化這段代碼:

  • 方式一:將隱藏邏輯去掉
1
2
3
4
5
6
7
8
9
10
11
public  boolean  isExpired(String key) {
         // 當前時間戳
         long  curTimestamp = DateUtils.nowUnixTime();
         // 獲取key的存入時間戳
         long  storeTimestamp = getStoreTimestamp(key);
        
         if  (curTimestamp - storeTimestamp > MAX_EXPIRE_SECONDS) {
             return  true ;
         }
         return  false ;
  }
  • 方式二:改變函數名字
1
2
3
4
5
6
7
8
9
10
11
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!這絕對不是明智的方式。假如一開始產品的需求是通過學生姓名查詢學生信息,寫出來的可能是這樣的函數:

1
public  List<Student> getByName(String name);

  然后突然又有一天產品提出了新的需求,希望同時可以通過姓名和電話號碼來查詢學生信息,那么函數可能變成這樣了:

1
public  List<Student> getByNameAndMobile(String name, String mobile);

  接着,沒過多久,產品又希望根據學生年齡來查詢學生信息,那么函數可能變成這樣了:

1
public  List<Student> getByNameAndMobileAndAge(String name, String mobile,  int  age);

  如果這樣來給函數命名,那么你的噩夢大門即將打開。

  通常比較好的做法是:

  • 如果是通過主鍵id來查詢,那么可以通過by來連接查詢信息,比如:

1
public  Student getByStudentId( long  studentId);
  • 如果是通過其他屬性來查詢,並且未來會存在多個組合查詢的可能性,建議進行封裝,比如:

1
public  List<Student> getStudents(StudentSearchParam searchParam);

  

  最后,建議大家平時在寫代碼過程中,不要怕在函數命名上耗費時間,一個好的函數命名在后期會大大減少你代碼重構的成本,爭取對函數命名做到"見字如面"~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM