在上一篇文章中跟大家分享了關於函式命名的一些實踐心得,今天我們繼續命名這個話題,來講一講如何對變數命名。
以下是本文的目錄大綱:
一. 變數命名風格
二. 變數命名最高境界
三. 變數命名最佳實踐
若有不正之處請多多諒解,並歡迎批評指正。
請尊重作者勞動成果,轉載請標明原文連結:
https://www.cnblogs.com/dolphin0520/p/10639167.html
一.變數命名風格
變數命名風格通常會根據不同的變數型別來區分,以Java語言為例,根據變數型別不同有兩種命名風格:
1)類成員變數、區域性變數
類成員變數、區域性變數通常採用駝峰命名風格,如下:
String userName;
複製程式碼
2)靜態成員變數、列舉值、常量
靜態成員變數、列舉值、常量通常採用所有字母大寫、多個單詞以英文下劃線連線,如:
public static final int MAX_YEARS = 25;
// 建議列舉類都以Enum結尾
enum ColorEnum {
RED(0, "紅色"),
YELLOW(1, "黃色"),
GREEN(2, "綠色"),
WHITE(3, "白色"),
BLACK(4, "黑色");
private int code;
private String name;
Color(int code, String name) {
this.code = code;
this.name = name;
}
}複製程式碼
二.變數命名最高境界
在函式命名那篇中我們說的函式命名最高境界是見字如面,那麼對於變數命名來說,最高境界是什麼呢? 我認為是:自解釋,即"程式碼即註釋"。
為什麼這麼說呢,因為通常來說一個函式是會有函式註釋的,即使函式名字取的不好,如果註釋寫的比較清楚,對於後續維護人員來說也是瞭解函式具體功能的一種方式。
而變數則不同,在一個工程裡面,變數的數量遠遠大於函式的數量,所以不太可能對於每個變數都去寫註釋,所以如果一個工程的變數命名很糟糕,那麼對於後續維護人員來說將是毀滅性的打擊,因為每讀到一個變數,可能就需要去猜測變數的含義,我想沒有哪個人願意讀到這樣的程式碼,永遠記住一點:"程式碼是寫給人看的,不是寫給機器看的"。
譬如下面這段程式碼的命名就非常糟糕:
ppn = (cpn > 1) ? (cpn - 1) : cpn;
npn = (cpn < tpn) ? (cpn + 1) : tpn;
p = new Page(ppn, cpn, npn, tpn);複製程式碼
上面這段程式碼估計只有原作者清楚地知道各個變數的含義是啥了,
如果修改為下面這種寫法,可讀性會好很多,並且一目瞭然,很容易知道其大概意圖是計算分頁資訊:
prePageNum = (curPageNum > 1) ? (curPageNum - 1) : curPageNum;
nextPageNum = (curPageNum < totalPageNum) ? (curPageNum + 1) : totalPageNum;
page = new Page(prePageNum, curPageNum, nextPageNum, totalPageNum);複製程式碼
三.變數命名最佳實踐
1)採用名詞或者形容詞來命名變數
變數一般情況下建議使用名詞、名字組合或者形容詞,因為變數一般形容的是一種事物或者事物的屬性,所以用名詞或者名片語合更容易讓人理解,而形容詞一般用於bool型別的變數。
2)避免使用單字母變數,儘量細化變數含義
在程式中,儘量避免使用單字母變數,唯一可以接受使用單字母變數的場景只有for迴圈,不過還是不太推薦在for迴圈中使用單字母變數(用pos、index比for迴圈的i、j、k要好很多)。
舉個例子,比如下面這行程式碼:
double calConeVolume(double b, double d) {
return Math.PI * b * b * d / 3;
}複製程式碼
咋一看這個函式引數感覺挺清晰,但是一細看,b是什麼?d又是什麼?如果我要用這個函式,該怎麼傳參?估計大部人是一臉懵逼狀,只能進去看實際的函式實現才知道b是圓錐體半徑,d是圓錐體高度;
那麼怎麼優化這段程式碼命名呢?其實很簡單,稍微細化一下變數含義,讓變數名自己去表達實際意圖:
double calConeVolume(double radius, double height) {
return Math.PI * radius * radius * height / 3;
}複製程式碼
3)變數命名前後用詞需統一
在同一個工程或者一個場景下,變數命名風格需前後統一,比如total和sum都能表示總計的意思,那麼所有需要用到"總計"含義的地方要麼全部使用total、要麼全部使用sum。
保持前後命名風格統一是保證工程程式碼良好可讀性的關鍵保證。
4)集合變數用型別或者複數s作為字尾
在java中,有很多集合,比如List、Map、Set等,那麼集合變數該怎麼命名呢?
一般可採取兩種方式:
使用複數s結尾
List<Student> students = new ArrayList<>();
複製程式碼
用集合型別作為字尾
List<Student> studentList = new ArrayList<>();
複製程式碼
上面兩種方式均可,沒有比較明顯的偏好,根據實際場景決定。第一種方式相對更簡潔,第二種在區域性作用域裡面有多種相關的集合變數時區分度更大,比如:
List<Student> studentList = new ArrayList<>();
Map<Long, Student> studentMap = Maps.newHashMap();
for (Student stu : studentList) {
studentMap.put(stu.getId, stu);
}複製程式碼
我的建議是如果區域性作用域只有一種型別的集合,那麼推薦使用複數形式;如果區域性作用域有多個相關的集合型別,那麼推薦用型別結尾。
5)禁止使用is作為bool型別的類成員變數前置
在java中,禁止用is作為bool型別的類成員變數的字首,因為is作為字首會導致序列化/反序列出現問題,阿里的java程式碼規範中也明確提到了這一點,所以在寫程式碼的時候最好還是遵守公認的規範,不然哪天說不定就踩坑了。
6)儘量避免使用縮寫進行命名
有些時候,變數名可能有點長,不利於程式碼可讀性,因此很多時候在寫程式碼的時候喜歡用縮寫來命名,但這個不是一個好的習慣,除非使用的縮寫是大家都會使用的約定俗稱的縮寫。
比如下面這個命名:
int avgStudentAge;
複製程式碼
因為avg大家都知道是average的縮寫,所以這麼寫問題不大,不會引起歧義;
但是下面這種縮寫命名:
res
tmp
cnt
dep複製程式碼
就不是好的縮寫命名,因為不同的人閱讀可能會有不同的理解:
res => response、resource、result
tmp => temporary、template
cnt => count、content、context複製程式碼
附上一些約定俗稱的縮寫:
全稱 | 縮寫 |
identification | id |
average | avg |
maximum | max |
minimum | min |
buffer | buf |
error | err |
message | msg |
image | img |
length | len |
library | lib |
password | pwd |
position | pos |
data transfer object | dto |
view object | vo |
7)拋棄掉flag變數
國內一些早期的教材上,到處充斥著各種flag風格的變數,這種命名方式對於大型工程簡直就是噩夢,比如:
int flag = getDoctorFlag(doctorId);
if (flag == 1) {
//....
}複製程式碼
看到這段程式碼,讀者會有疑問flag變數的含義是什麼?flag值為1的時候又代表什麼含義?是醫生的值班/在崗狀態、還是醫生的身體狀態?估計讀者的內心是崩潰的。
如果優化成下面這種形式:
DutyStatus doctorDutyStatus = getDoctorDutyStatus(doctorId);
if (doctorDutyStatus == DutyStatus.ONLINE) {
// ...
}複製程式碼
就比上面的形式清晰多了,很容易看出來判斷的是醫生的值班/在崗狀態。
部落格園連結:https://www.cnblogs.com/dolphin0520/
公眾號: