下文主要来源于网上,我做了一些编辑整理。
“如果你不知道一件事物叫什么,
你就不知道它是什么。
如果你不知道这是什么,
你就不可能坐下来写代码。”
----萨姆·加德纳(Sam Gardiner)
1.大原则:见名知意,名副其实
对于方法或变量命名,编写者应当做到:一个初次接触代码的阅读者仅通过其名字就能揣测其用途,而不需要通过仔细代码来分辨。
反之,如果阅读者需要认真审视上下文才能了解其含义,可以认为其命名是令人费解的;如果其真实含义和名字存在分歧,则可以认为其命名是不恰当的。
下面是一个对照的例子:
令人费解的命名
|
好的命名
|
---|---|
x = x -xx xxx = fido + salesTax( fido ); x = x + LateFee(x1, x) + xxx; x = x + Interert(X1, x); |
balance = balance - lastPayment; monthlyTotal = newPurchases + addSalesTax( newPurchases ); balance = balance + evaluateLateFee( customerID, balance ) + monthlyTotal; balance = balance + addInterest( CustomerID, balance); |
2.命名细则:
原则
|
解释
|
---|---|
同一性 | 在编写一个子模块或派生类的时候,要遵循其基类或整体模块的命名风格,保持命名风格在整个模块中的同一性。如骆驼命名法,大括号位置等。 |
标识符组成 | 标识符采用英文单词(必要或无歧义可以加入数字或下划线)或其组合,应当直观且可以拼读,可望文知意,用词应当准确。 |
最小化长度 && 最大化信息量原则 |
在足够描述用途的前提下,尽量以最小词汇量去描述事物,如staff就比 company_person_collection要简捷易记。 也可采用有广泛共识的缩写后缀,如msg,idx,cnt,btn,id ,flg等,如果缩写共识度不高,请在取得同事们共识后用注释说明其含义。 变量/函数长度控制在4~18个字符内,有助于对代码的理解。 过长的变量:howLongDoesItTakeToOpenTheDoor, howBigIsTheMaterial… 简捷的变量:timeToOpenTheDoor, materialSize. |
避免过于相似 | 不要出现仅靠大小写区分的相似的标识符,例如“i”与“I”,“function”与“Function”等等。 |
正确命名具有互斥意义的标识符 |
用正确的反义词组命名具有互斥意义的标识符 ,如 add / remove begin / end create / destroy 这些有助于理解成对的变量/函数的意义. |
尽量避免名字中出现数字编号 | 尽量避免名字中出现数字编号,如value1,value2等,除非逻辑上的确需要编号。 |
少使用类型前缀 | C/C++程序员喜欢这么做,那是因为环境特殊。但在Java中并不提倡,最好从名字上就能揣测出其类型。加后缀说明是可以的。 |
少单独使用含义广泛的词 | 如data,info,value等。 |
能用主动语态的词就不用被动语态的词 |
能用主动就绝不用被动语态的词,便于用户理解,同时也遵守标识符的语法规则。 被动语态:class PlanEvents 主动语态:class EventPlanner/class Scheduler |
避免过度使用get作为方法前缀 | 应该用更精确的动词描述动作,如“请求”request,“获取”acquire,“查找”search/lookfor/find,“查询”inquire,“构建”build 或“创建”create |
3.名词、动词和形容词在命名中的使用
对于变量,一般采用名词命名,如salary;如果其含义较复杂,建议采用形容词+名词的形式,如totalSalary;如果不会产生歧义,可以使用名词+名词的方式,如minerSalavry,flightNumber, carColor
对于方法,一般采用动词+名词的方式命名,如drawBullet,cleanScreen; 也可以采用省略动词的介词+名词的形式,如onMessage,onAbort,onExit.
如用于限制范围,可以在名词前加入介词,如要修饰名词,可以在名词前加入形容词,如sumZombieFansCnt。
4.多使用常见的有共识的词汇
生僻词汇容易造成困惑,常见词汇易于达成共识。
词性
|
常见词汇
|
---|---|
名词 |
comparison比较(结果) ,decrement递减量 , decrement递减量 , dest/destination目标 , expected value/expectation:期望值 , idx:index的简写 , height高 ,increment递增量 , msg:message的简写 , num数字 , price价钱价格 , priority优先级 , rate比率 , score成绩分数 , src/source 源 , sum累计值 , total总和总计的 , usr/user用户 , weight重量 |
动词 |
access存取 , add添加 , append添加到尾部 , apply(to)适用于 , cancel取消 , can能做什么 , change交换 , compare比较 , contains包含 , crash崩溃 , create创建 , decode解码 , delete删除 , display显示 , encode编码 , erase 抹去 , evaluate计算 , execute执行 , exist存在 , fetch取回 , flush清空缓存 , get获得 , has有什么 , insert插入 , invoke调用 , is是什么 , list列举 , manage管理 , minus减 , need需要什么 , provide提供 , query查询 , remove 搬离 , run运行 , save保存 , select选择 , should应当做什么 , sort排序 , store存储 , submit提交 , update更新 |
形容词 |
avg/average平均 , corresponding相应的对应的 , decisive决定性的 , final最终的 , legal合法的,illegal不合法的 , max最大 , min最小 , often used/frequently used:常用的 , partly:部分的 , periodically:定期的 , relevant:相关的 , seldom used:不常用的 , time-consuming:耗时的, unpredictable:不可预计的 , unrecongnized:未被认定的 |
5.分类单词表
返回真伪值的方法
場所
|
单词
|
意义
|
例
|
---|---|---|---|
Prefix | is | 对象是否是所期待的状态 | isChecked |
Prefix | can | 对象能否执行所期待的动作 | canRemove |
Prefix | should | 调用方执行某个命令好还是不好 | shouldMigrate |
Prefix | has | 对象是否持有所期待的数据和属性 | hasObservers |
Prefix | needs | 调用方是否需要执行某个命令 | needsMigrate |
按需求才执行的方法
場所
|
单词
|
意义
|
例
|
---|---|---|---|
Suffix | IfNeeded | 需要的时候执行,不需要的时候什么都不做 | drawIfNeeded |
Prefix | might | 同上 | mightCreate |
Prefix | try | 尝试执行,失败时抛出异常或是返回errorcode | tryCreate |
Suffix | OrDefault | 尝试执行,失败时返回默认值 | getOrDefault |
Suffix | OrElse | 尝试执行、失败时返回实际参数中指定的值 | getOrElse |
Prefix | force | 强制尝试执行。error抛出异常或是返回值 | forceCreate, forceStop |
异步相关方法
場所
|
单词
|
意义
|
例
|
---|---|---|---|
Prefix | blocking | 线程阻塞方法 | blockingGetUser |
Suffix | InBackground | 执行在后台的线程 | doInBackground |
Suffix | Async | 异步方法 | sendAsync |
Suffix | Sync | 对应已有异步方法的同步方法 | sendSync |
Prefix or Stem | schedule | Job和Task放入队列 | schedule, scheduleJob |
Prefix or Stem | post | 同上 | postJob |
Prefix or Stem | execute | 执行异步方法(注:我一般拿这个做同步方法名) | execute, executeTask |
Prefix or Stem | start | 同上 | start, startJob |
Prefix or Stem | cancel | 停止异步方法 | cancel, cancelJob |
Prefix or Stem | stop | 同上 | stop, stopJob |
回调方法
場所
|
单词
|
意义
|
例
|
---|---|---|---|
Prefix | on | 事件发生时执行 | onCompleted |
Prefix | before | 事件发生前执行 | beforeUpdate |
Prefix | pre | 同上 | preUpdate |
Prefix | will | 同上 | willUpdate |
Prefix | after | 事件发生后执行 | afterUpdate |
Prefix | post | 同上 | postUpdate |
Prefix | did | 同上 | didUpdate |
Prefix | should | 确认事件是否可以发生时执行 | shouldUpdate |
与集合操作相关的方法
单词
|
意义
|
例
|
---|---|---|
contains | 是否持有与指定对象相同的对象 | contains |
add | 添加 | addJob |
append | 添加 | appendJob |
insert | 插入到下标n | insertJob |
put | 添加与key对应的元素 | putJob |
remove | 移除元素 | removeJob |
enqueue | 添加到队列的最末位 | enqueueJob |
dequeue | 从队列中头部取出并移除 | dequeueJob |
push | 添加到栈头 | pushJob |
pop | 从栈头取出并移除 | popJob |
peek | 从栈头取出但不移除 | peekJob |
find | 寻找符合条件的某物 | findById |
与状态相关的方法
单词
|
意义
|
例
|
---|---|---|
ensure | 检查是否为期待的状态,不是则抛出异常或返回error code | ensureCapacity |
validate | 检查是否为正确的状态,不是则抛出异常或返回error code | validateInputs |
操作对象生命周期的方法
单词
|
意义
|
例
|
---|---|---|
initialize | 初始化。也可作为延迟初始化使用 | initialize |
abandon | 销毁的替代 | abandon |
destroy | 同上 | destroy |
dispose | 同上 | dispose |
与数据相关的方法
单词
|
意义
|
例
|
---|---|---|
create | 新创建 | createAccount |
new | 新创建 | newAccount |
from | 从既有的某物新建,或是从其他的数据新建 | fromConfig |
to | 转换 | toString |
update | 更新既有某物 | updateAccount |
load | 读取 | loadAccount |
fetch | 远程读取 | fetchAccount |
delete | 删除 | deleteAccount |
remove | 删除 | removeAccount |
save | 保存 | saveAccount |
store | 保存 | storeAccount |
commit | 保存 | commitChange |
apply | 保存或应用 | applyChange |
clear | 清除数据或是恢复到初始状态 | clearAll |
reset | 清除数据或是恢复到初始状态 | resetAll |
常见布尔变量:
单词
|
意义
|
---|---|
done | 完成 |
error | 错误 |
success/ok | 成功 |
available | 可用 |
found | 已找到 |
complete(d) | 完成 |
6.结语
对于非英语系程序员来说,变量的起名和函数的命名都是一件令人头疼的事情,主因是词汇量和对单词的认知程度先天有限.....但我们编码是为了让别人或未来的自己更好的去阅读,而不是“迷惑”别人或自己。
无论是想要有效的管理一个复杂程度稍高的代码体系,或是维护自己的代码库,能有一套统一的、清晰明了的命名原则是一件事半功倍的有效手段,利人利己,值得花不多的工夫把它掌握熟悉起来。
每个东西都有一个名称,每个名称只用于一件事。使用多个词来表示相同的事物,或者同一个词来表示不同的事物,会浪费认知的努力并且可能导致混淆。这不仅适用于代码,而且适用于我们工作环境中的所有内容。