为什么需要命名规范?有哪些命名规范?
一、先想明白:为什么命名这么重要?
以中国来说,不同地方之间都有着不同的方言。"土豆"这是来自官方的说法,而他还有着其他不同的叫法类似"地蛋"、"洋芋"、"薯仔"。不同的说法可能都指向同一个东西。但是,不同的人可能对同一个东西有不同的理解。而命名规范就是解决这个问题的。
例如你一个月前写了一段代码,代码里有这么一行:
ini
int d = 30;
这个 d 是什么?天数?直径?距离?折扣?你大概率已经忘了。
又比如你写了一个方法,方法名是 Discount,这是一个获取折扣的方法。但是是以一个类名的开头,而不是以一个动词开头,别人可能会以为这是一个类,而不是一个方法。
好名字能让别人不读你的实现逻辑,光看名字就知道这行代码在干嘛。
二、核心原则:见名知意
见名知意是指,看到名字,就知道它是干嘛的,不需要回头去查定义。
我们用这个原则来检验几个例子:
| 反例 | 问题 | 正例 |
|---|---|---|
int d; |
谁知道 d 是啥 | int days; |
String n; |
n = name? number? | String studentName; |
List list; |
什么 list? | List<Student> studentList; |
void doIt(); |
do what? | void enrollStudent(); |
int a1, a2, a3; |
三个数到底啥关系 | int chineseScore, mathScore, englishScore; |
把名字单独拎出来看,你能猜出它是干嘛的就是好名字。
三、具体规则速查
1. 类名:大驼峰(PascalCase)
每个单词首字母都大写,拼在一起:
kotlin
// 例
class StudentInfo {}
class OrderService {}
class UserController {}
2. 方法名:小驼峰(camelCase)
每个单词首字母都小写,拼在一起:
csharp
// 例
void enrollStudent() {}
void updateOrderStatus() {}
3. 变量名:小驼峰,和方法同款
arduino
// 例
int studentAge;
String orderId;
boolean isExpired;
4. 常量:全大写 + 下划线
固定不变的值,全大写,单词之间用下划线隔开:
arduino
// 例
static final int MAX_AGE = 150;
static final String SYSTEM_NAME = "学生管理系统";
5. 包名 / 目录名:全小写
arduino
// 例
com.myapp.service
com.myapp.controller
6.布尔变量:is/has/should/should not 开头
arduino
// 例
boolean isExpired;
boolean hasPermission;
boolean shouldNotify;
命名方法速记:类就像一张图纸,方法就像图纸上的一个操作。所以类的命名应该是一个名词,方法的命名应该是一个动词。常量需要全场醒目,所以用全大写 + 下划线。包名全小写。布尔需判断所以用has/should/is。
四、初学者最容易踩的几个坑
坑 1:用拼音
arduino
// 不好
String xingming; // 这是拼音!
int nianling;
// 好
String name;
int age;
不仅外国人难以理解,中国人也会感觉不好直译。
坑 2:过度缩写
scss
// 不好
Stdnt st = new Stdnt();
CalcTotalPirce();
// 好
Student student = new Student();
calculateTotalPrice();
只有行业里公认的缩写才能用,比如:
-
id(identity) -
url -
html -
userDao(DAO 是通用术语)
其他时候,写完整单词比缩写好 ------ 多打几个字母而已。
坑 3:用无意义的临时变量名
ini
// 不好
for (int i = 0; i < list.size(); i++) {
Object obj = list.get(i);
System.out.println(obj);
}
// 稍微好一点(当你明确知道 list 里是什么)
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
System.out.println(s.getName());
}
注意:循环里的 i、j 是公认惯例,可以接受。但 obj、temp、data 这种,能写具体就写具体。
坑 4:名字和实际功能对不上
csharp
// 不好
// 方法名叫 getUser,结果它干的是"删除用户"
User getUser() {
db.deleteUser();
return null;
}
容易误导读代码的人。
一句话总结
好的命名就是在下次见到它的时候,不用查看注释,不用实现,只看名字就知道这段代码的功能。
就像你和她之间,总以为留下一个名字,一段标记,就能永久封存当下的感受,以为日后重逢,仅凭这个代号,就能瞬间拾起当初所有心动与热忱。可等到时隔许久再回头,才残忍地发现,名字还完好地留在原地,可当初写下它时的心境、情绪与想法,早已慢慢消散。明明字符没有变,却再也读不懂当年的自己,就像有些人,名字依旧熟悉,可属于你们之间的那份感觉,再也找不回来了。
但代码不一样。人的情绪经不起时间冲刷,可我们能用一套统一的命名规范,给代码定下不变的约定。多年之后再次打开这份代码,不必翻阅冗长的注释,不必一层层钻进复杂的实现逻辑,单单看见这个名字,就能读懂这段代码的作用。规范留不住敲下代码那一刻的灵光一闪或是疲惫落寞,却能守住代码本身的含义。哪怕时光流逝,当初的思绪早已模糊,只要命名遵守规范,我们依旧能认出它的功能,读懂它的意图。