簡潔清爽的代碼風(fēng)格應(yīng)該是大多數(shù)工程師所期待的钓账。在工作中筆者常常因?yàn)槠鹈侄m結(jié)唠粥,夸張點(diǎn)可以說是編程5分鐘浊竟,命名兩小時(shí)!究竟為什么命名成為了工作中的攔路虎淫奔。
每個(gè)公司都有不同的標(biāo)準(zhǔn)山涡,目的是為了保持統(tǒng)一,減少溝通成本唆迁,提升團(tuán)隊(duì)研發(fā)效能鸭丛。所以本文中是筆者結(jié)合阿里巴巴開發(fā)規(guī)范,以及工作中的見聞針對(duì)Java領(lǐng)域相關(guān)命名進(jìn)行整理和總結(jié)唐责,僅供參考鳞溉。
一、Java中的命名規(guī)范
好的命名能體現(xiàn)出代碼的特征鼠哥,含義或者是用途熟菲,讓閱讀者可以根據(jù)名稱的含義快速厘清程序的脈絡(luò)。不同語言中采用的命名形式大相徑庭朴恳,Java中常用到的命名形式共有三種抄罕,既首字母大寫的UpperCamelCase,首字母小寫的lowerCamelCase以及全部大寫的并用下劃線分割單詞的UPPER_CAMEL_UNSER_SCORE于颖。通常約定呆贿,類一般采用大駝峰命名,方法和局部變量使用小駝峰命名,而大寫下劃線命名通常是常量和枚舉中使用做入。
類型 | 約束 | 例 |
---|---|---|
項(xiàng)目名 | 全部小寫冒晰,多個(gè)單詞用中劃線分隔‘-’ | spring-cloud |
包名 | 全部小寫 | com.alibaba.fastjson |
類名 | 單詞首字母大寫 | Feature, ParserConfig,DefaultFieldDeserializer |
變量名 | 首字母小寫,多個(gè)單詞組成時(shí)竟块,除首個(gè)單詞壶运,其他單詞首字母都要大寫 | password, userName |
常量名 | 全部大寫,多個(gè)單詞浪秘,用'_'分隔 | CACHE_EXPIRED_TIME |
方法 | 同變量 | read(), readObject(), getById() |
二蒋情、包命名
包名統(tǒng)一使用小寫,點(diǎn)分隔符之間有且僅有一個(gè)自然語義的英文單詞或者多個(gè)單詞自然連接到一塊(如 springframework秫逝,deepspace不需要使用任何分割)恕出。包名統(tǒng)一使用單數(shù)形式询枚,如果類命有復(fù)數(shù)含義违帆,則可以使用復(fù)數(shù)形式。
包名的構(gòu)成可以分為以下幾四部分【前綴】 【發(fā)起者名】【項(xiàng)目名】【模塊名】金蜀。常見的前綴可以分為以下幾種:
前綴名 | 例 | 含義 |
---|---|---|
indi(或onem ) | indi.發(fā)起者名.項(xiàng)目名.模塊名.…… | 個(gè)體項(xiàng)目刷后,指?jìng)€(gè)人發(fā)起,但非自己獨(dú)自完成的項(xiàng)目渊抄,可公開或私有項(xiàng)目尝胆,copyright主要屬于發(fā)起者。 |
pers | pers.個(gè)人名.項(xiàng)目名.模塊名.…… | 個(gè)人項(xiàng)目护桦,指?jìng)€(gè)人發(fā)起含衔,獨(dú)自完成,可分享的項(xiàng)目二庵,copyright主要屬于個(gè)人 |
priv | priv.個(gè)人名.項(xiàng)目名.模塊名.…… | 私有項(xiàng)目贪染,指?jìng)€(gè)人發(fā)起,獨(dú)自完成催享,非公開的私人使用的項(xiàng)目杭隙,copyright屬于個(gè)人。 |
team | team.團(tuán)隊(duì)名.項(xiàng)目名.模塊名.…… | 團(tuán)隊(duì)項(xiàng)目因妙,指由團(tuán)隊(duì)發(fā)起痰憎,并由該團(tuán)隊(duì)開發(fā)的項(xiàng)目,copyright屬于該團(tuán)隊(duì)所有 |
頂級(jí)域名 | com.公司名.項(xiàng)目名.模塊名.…… | 公司項(xiàng)目攀涵,copyright由項(xiàng)目發(fā)起的公司所有 |
三铣耘、類命名
類名使用大駝峰命名形式,類命通常時(shí)名詞或名詞短語以故,接口名除了用名詞和名詞短語以外蜗细,還可以使用形容詞或形容詞短語,如Cloneable据德,Callable等鳄乏,表示實(shí)現(xiàn)該接口的類有某種功能或能力跷车。對(duì)于測(cè)試類則以它要測(cè)試的類開頭,以Test結(jié)尾橱野,如HashMapTest朽缴。
對(duì)于一些特殊特有名詞縮寫也可以使用全大寫命名,比如XMLHttpRequest水援,不過筆者認(rèn)為縮寫三個(gè)字母以內(nèi)都大寫密强,超過三個(gè)字母則按照要給單詞算。這個(gè)沒有標(biāo)準(zhǔn)如阿里巴巴中fastjson用JSONObject作為類命蜗元,而google則使用JsonObjectRequest命名或渤,對(duì)于這種特殊的縮寫,原則是統(tǒng)一就好奕扣。
屬性 | 約束 | 例 |
---|---|---|
抽象類 | Abstract 或者 Base 開頭 | BaseUserService |
枚舉類 | Enum 作為后綴 | GenderEnum |
工具類 | Utils作為后綴 | StringUtils |
異常類 | Exception結(jié)尾 | RuntimeException |
接口實(shí)現(xiàn)類 | 接口名+ Impl | UserServiceImpl |
領(lǐng)域模型相關(guān) | /DO/DTO/VO/DAO | 正例:UserDAO 反例: UserDo薪鹦, UserDao |
設(shè)計(jì)模式相關(guān)類 | Builder,F(xiàn)actory等 | 當(dāng)使用到設(shè)計(jì)模式時(shí)惯豆,需要使用對(duì)應(yīng)的設(shè)計(jì)模式作為后綴池磁,如ThreadFactory |
處理特定功能的 | Handler,Predicate, Validator | 表示處理器楷兽,校驗(yàn)器地熄,斷言,這些類工廠還有配套的方法名如handle芯杀,predicate端考,validate |
測(cè)試類 | Test結(jié)尾 | UserServiceTest, 表示用來測(cè)試UserService類的 |
MVC分層 | Controller揭厚,Service却特,ServiceImpl,DAO后綴 | UserManageController棋弥,UserManageDAO |
四核偿、方法
方法命名采用小駝峰的形式,首字小寫顽染,往后的每個(gè)單詞首字母都要大寫漾岳。 和類名不同的是,方法命名一般為動(dòng)詞或動(dòng)詞短語粉寞,與參數(shù)或參數(shù)名共同組成動(dòng)賓短語尼荆,即動(dòng)詞 + 名詞。一個(gè)好的函數(shù)名一般能通過名字直接獲知該函數(shù)實(shí)現(xiàn)什么樣的功能唧垦。
4.1 返回真?zhèn)沃档姆椒?/h3>
注:Prefix-前綴捅儒,Suffix-后綴,Alone-單獨(dú)使用
位置 | 單詞 | 意義 | 例 |
---|---|---|---|
Prefix | is | 對(duì)象是否符合期待的狀態(tài) | isValid |
Prefix | can | 對(duì)象能否執(zhí)行所期待的動(dòng)作 | canRemove |
Prefix | should | 調(diào)用方執(zhí)行某個(gè)命令或方法是好還是不好,應(yīng)不應(yīng)該,或者說推薦還是不推薦 | shouldMigrate |
Prefix | has | 對(duì)象是否持有所期待的數(shù)據(jù)和屬性 | hasObservers |
Prefix | needs | 調(diào)用方是否需要執(zhí)行某個(gè)命令或方法 | needsMigrate |
4.2 用來檢查的方法
單詞 | 意義 | 例 |
---|---|---|
ensure | 檢查是否為期待的狀態(tài)巧还,不是則拋出異潮廾В或返回error code | ensureCapacity |
validate | 檢查是否為正確的狀態(tài),不是則拋出異臭锏唬或返回error code | validateInputs |
4.3 按需求才執(zhí)行的方法
位置 | 單詞 | 意義 | 例 |
---|---|---|---|
Suffix | IfNeeded | 需要的時(shí)候執(zhí)行澎怒,不需要的時(shí)候什么都不做 | drawIfNeeded |
Prefix | might | 同上 | mightCreate |
Prefix | try | 嘗試執(zhí)行,失敗時(shí)拋出異辰纂梗或是返回errorcode | tryCreate |
Suffix | OrDefault | 嘗試執(zhí)行喷面,失敗時(shí)返回默認(rèn)值 | getOrDefault |
Suffix | OrElse | 嘗試執(zhí)行、失敗時(shí)返回實(shí)際參數(shù)中指定的值 | getOrElse |
Prefix | force | 強(qiáng)制嘗試執(zhí)行走孽。error拋出異尘灞玻或是返回值 | forceCreate, forceStop |
4.4 異步相關(guān)方法
位置 | 單詞 | 意義 | 例 |
---|---|---|---|
Prefix | blocking | 線程阻塞方法 | blockingGetUser |
Suffix | InBackground | 執(zhí)行在后臺(tái)的線程 | doInBackground |
Suffix | Async | 異步方法 | sendAsync |
Suffix | Sync | 對(duì)應(yīng)已有異步方法的同步方法 | sendSync |
Prefix or Alone | schedule | Job和Task放入隊(duì)列 | schedule, scheduleJob |
Prefix or Alone | post | 同上 | postJob |
Prefix or Alone | execute | 執(zhí)行異步方法(注:我一般拿這個(gè)做同步方法名) | execute, executeTask |
Prefix or Alone | start | 同上 | start, startJob |
Prefix or Alone | cancel | 停止異步方法 | cancel, cancelJob |
Prefix or Alone | stop | 同上 | stop, stopJob |
4.5 回調(diào)方法
位置 | 單詞 | 意義 | 例 |
---|---|---|---|
Prefix | on | 事件發(fā)生時(shí)執(zhí)行 | onCompleted |
Prefix | before | 事件發(fā)生前執(zhí)行 | beforeUpdate |
Prefix | pre | 同上 | preUpdate |
Prefix | will | 同上 | willUpdate |
Prefix | after | 事件發(fā)生后執(zhí)行 | afterUpdate |
Prefix | post | 同上 | postUpdate |
Prefix | did | 同上 | didUpdate |
Prefix | should | 確認(rèn)事件是否可以發(fā)生時(shí)執(zhí)行 | shouldUpdate |
4.6 操作對(duì)象生命周期的方法
單詞 | 意義 | 例 |
---|---|---|
initialize | 初始化。也可作為延遲初始化使用 | initialize |
pause | 暫停 | onPause 磕瓷,pause |
stop | 停止 | onStop盒齿,stop |
abandon | 銷毀的替代 | abandon |
destroy | 同上 | destroy |
dispose | 同上 | dispose |
4.7 與集合操作相關(guān)的方法
單詞 | 意義 | 例 |
---|---|---|
contains | 是否持有與指定對(duì)象相同的對(duì)象 | contains |
add | 添加 | addJob |
append | 添加 | appendJob |
insert | 插入到下標(biāo)n | insertJob |
put | 添加與key對(duì)應(yīng)的元素 | putJob |
remove | 移除元素 | removeJob |
enqueue | 添加到隊(duì)列的最末位 | enqueueJob |
dequeue | 從隊(duì)列中頭部取出并移除 | dequeueJob |
push | 添加到棧頭 | pushJob |
pop | 從棧頭取出并移除 | popJob |
peek | 從棧頭取出但不移除 | peekJob |
find | 尋找符合條件的某物 | findById |
4.8 與數(shù)據(jù)相關(guān)的方法
單詞 | 意義 | 例 |
---|---|---|
create | 新創(chuàng)建 | createAccount |
new | 新創(chuàng)建 | newAccount |
from | 從既有的某物新建,或是從其他的數(shù)據(jù)新建 | fromConfig |
to | 轉(zhuǎn)換 | toString |
update | 更新既有某物 | updateAccount |
load | 讀取 | loadAccount |
fetch | 遠(yuǎn)程讀取 | fetchAccount |
delete | 刪除 | deleteAccount |
remove | 刪除 | removeAccount |
save | 保存 | saveAccount |
store | 保存 | storeAccount |
commit | 保存 | commitChange |
apply | 保存或應(yīng)用 | applyChange |
clear | 清除數(shù)據(jù)或是恢復(fù)到初始狀態(tài) | clearAll |
reset | 清除數(shù)據(jù)或是恢復(fù)到初始狀態(tài) | resetAll |
4.9 成對(duì)出現(xiàn)的動(dòng)詞
單詞 | 意義 |
---|---|
get獲取 | set 設(shè)置 |
add 增加 | remove 刪除 |
create 創(chuàng)建 | destory 移除 |
start 啟動(dòng) | stop 停止 |
open 打開 | close 關(guān)閉 |
read 讀取 | write 寫入 |
load 載入 | save 保存 |
create 創(chuàng)建 | destroy 銷毀 |
begin 開始 | end 結(jié)束 |
backup 備份 | restore 恢復(fù) |
import 導(dǎo)入 | export 導(dǎo)出 |
split 分割 | merge 合并 |
inject 注入 | extract 提取 |
attach 附著 | detach 脫離 |
bind 綁定 | separate 分離 |
view 查看 | browse 瀏覽 |
edit 編輯 | modify 修改 |
select 選取 | mark 標(biāo)記 |
copy 復(fù)制 | paste 粘貼 |
undo 撤銷 | redo 重做 |
insert 插入 | delete 移除 |
add 加入 | append 添加 |
clean 清理 | clear 清除 |
index 索引 | sort 排序 |
find 查找 | search 搜索 |
increase 增加 | decrease 減少 |
play 播放 | pause 暫停 |
launch 啟動(dòng) | run 運(yùn)行 |
compile 編譯 | execute 執(zhí)行 |
debug 調(diào)試 | trace 跟蹤 |
observe 觀察 | listen 監(jiān)聽 |
build 構(gòu)建 | publish 發(fā)布 |
input 輸入 | output 輸出 |
encode 編碼 | decode 解碼 |
encrypt 加密 | decrypt 解密 |
compress 壓縮 | decompress 解壓縮 |
pack 打包 | unpack 解包 |
parse 解析 | emit 生成 |
connect 連接 | disconnect 斷開 |
send 發(fā)送 | receive 接收 |
download 下載 | upload 上傳 |
refresh 刷新 | synchronize 同步 |
update 更新 | revert 復(fù)原 |
lock 鎖定 | unlock 解鎖 |
check out 簽出 | check in 簽入 |
submit 提交 | commit 交付 |
push 推 | pull 拉 |
expand 展開 | collapse 折疊 |
begin 起始 | end 結(jié)束 |
start 開始 | finish 完成 |
enter 進(jìn)入 | exit 退出 |
abort 放棄 | quit 離開 |
obsolete 廢棄 | depreciate 廢舊 |
collect 收集 | aggregate 聚集 |
五生宛、變量&常量命名
5.1 變量命名
變量是指在程序運(yùn)行中可以改變其值的量县昂,包括成員變量和局部變量肮柜。變量名由多單詞組成時(shí)陷舅,第一個(gè)單詞的首字母小寫,其后單詞的首字母大寫审洞,俗稱駱駝式命名法(也稱駝峰命名法)莱睁,如 computedValues,index芒澜、變量命名時(shí)仰剿,盡量簡短且能清楚的表達(dá)變量的作用,命名體現(xiàn)具體的業(yè)務(wù)含義即可痴晦。
變量名不應(yīng)以下劃線或美元符號(hào)開頭南吮,盡管這在語法上是允許的。變量名應(yīng)簡短且富于描述誊酌。變量名的選用應(yīng)該易于記憶部凑,即,能夠指出其用途碧浊。盡量避免單個(gè)字符的變量名涂邀,除非是一次性的臨時(shí)變量。pojo中的布爾變量箱锐,都不要加is(數(shù)據(jù)庫中的布爾字段全都要加 is_ 前綴)比勉。
5.2 常量命名
常量命名CONSTANT_CASE,一般采用全部大寫(作為方法參數(shù)時(shí)除外),單詞間用下劃線分割浩聋。那么什么是常量呢观蜗?
常量是在作用域內(nèi)保持不變的值,一般使用final進(jìn)行修飾衣洁。一般分為三種嫂便,全局常量(public static final修飾),類內(nèi)常量(private static final 修飾)以及局部常量(方法內(nèi)闸与,或者參數(shù)中的常量)毙替,局部常量比較特殊,通常采用小駝峰命名即可践樱。
/** * 一個(gè)demo * * @author Jann Lee * @date 2019-12-07 00:25 **/public class HelloWorld { /** * 局部常量(正例) */ public static final long USER_MESSAGE_CACHE_EXPIRE_TIME = 3600; /** * 局部常量(反例厂画,命名不清晰) */ public static final long MESSAGE_CACHE_TIME = 3600; /** * 全局常量 */ private static final String ERROR_MESSAGE = " error message"; /** * 成員變量 */ private int currentUserId; /** * 控制臺(tái)打印 {@code message} 信息 * * @param message 消息體,局部常量 */ public void sayHello(final String message){ System.out.println("Hello world!"); } }
常量一般都有自己的業(yè)務(wù)含義,不要害怕長度過長而進(jìn)行省略或者縮寫拷邢。如袱院,用戶消息緩存過期時(shí)間的表示,那種方式更佳清晰瞭稼,交給你來評(píng)判忽洛。
通用命名規(guī)則
- 盡量不要使用拼音;杜絕拼音和英文混用环肘。對(duì)于一些通用的表示或者難以用英文描述的可以采用拼音欲虚,一旦采用拼音就堅(jiān)決不能和英文混用。
正例: BeiJing悔雹, HangZhou
反例: validateCanShu - 命名過程中盡量不要出現(xiàn)特殊的字符复哆,常量除外。
- 盡量不要和jdk或者框架中已存在的類重名腌零,也不能使用java中的關(guān)鍵字命名梯找。
- 妙用介詞,如for(可以用同音的4代替), to(可用同音的2代替), from, with益涧,of等锈锤。
如類名采用User4RedisDO,方法名getUserInfoFromRedis闲询,convertJson2Map等久免。
六、代碼注解
6.1 注解的原則
好的命名增加代碼閱讀性嘹裂,代碼的命名往往有嚴(yán)格的限制妄壶。而注解不同,程序員往往可以自由發(fā)揮寄狼,單并不意味著可以為所欲為之胡作非為丁寄。優(yōu)雅的注解通常要滿足三要素氨淌。
- Nothing is strange
沒有注解的代碼對(duì)于閱讀者非常不友好,哪怕代碼寫的在清除伊磺,閱讀者至少從心理上會(huì)有抵觸盛正,更何況代碼中往往有許多復(fù)雜的邏輯,所以一定要寫注解屑埋,不僅要記錄代碼的邏輯豪筝,還有說清楚修改的邏輯。 - Less is more
從代碼維護(hù)角度來講摘能,代碼中的注解一定是精華中的精華续崖。合理清晰的命名能讓代碼易于理解,對(duì)于邏輯簡單且命名規(guī)范团搞,能夠清楚表達(dá)代碼功能的代碼不需要注解严望。濫用注解會(huì)增加額外的負(fù)擔(dān),更何況大部分都是廢話逻恐。
// 根據(jù)id獲取信息【廢話注解】getMessageById(id)
- Advance with the time
注解應(yīng)該隨著代碼的變動(dòng)而改變像吻,注解表達(dá)的信息要與代碼中完全一致。通常情況下修改代碼后一定要修改注解复隆。
6.2 注解格式
注解大體上可以分為兩種拨匆,一種是javadoc注解,另一種是簡單注解挽拂。javadoc注解可以生成JavaAPI為外部用戶提供有效的支持javadoc注解通常在使用IDEA惭每,或者Eclipse等開發(fā)工具時(shí)都可以自動(dòng)生成,也支持自定義的注解模板轻局,僅需要對(duì)對(duì)應(yīng)的字段進(jìn)行解釋洪鸭。參與同一項(xiàng)目開發(fā)的同學(xué),盡量設(shè)置成相同的注解模板仑扑。
a. 包注解
包注解在工作中往往比較特殊,通過包注解可以快速知悉當(dāng)前包下代碼是用來實(shí)現(xiàn)哪些功能置鼻,強(qiáng)烈建議工作中加上镇饮,尤其是對(duì)于一些比較復(fù)雜的包,包注解一般在包的根目錄下箕母,名稱統(tǒng)一為package-info.java储藐。
/** * 落地也質(zhì)量檢測(cè) * 1\. 用來解決什么問題 * 對(duì)廣告主投放的廣告落地頁進(jìn)行性能檢測(cè),模擬不同的系統(tǒng)嘶是,如Android钙勃,IOS等; 模擬不同的網(wǎng)絡(luò):2G,3G聂喇,4G辖源,wifi等 * * 2\. 如何實(shí)現(xiàn) * 基于chrome瀏覽器蔚携,用chromedriver驅(qū)動(dòng)瀏覽器,設(shè)置對(duì)應(yīng)的網(wǎng)絡(luò)克饶,OS參數(shù)酝蜒,獲取到瀏覽器返回結(jié)果。 * * 注意: 網(wǎng)絡(luò)環(huán)境配置信息{@link cn.mycookies.landingpagecheck.meta.NetWorkSpeedEnum}目前使用是常規(guī)速度矾湃,可以根據(jù)實(shí)際情況進(jìn)行調(diào)整 * * @author cruder * @time 2019/12/7 20:3 下午 */package cn.mycookies.landingpagecheck;
b. 類注接
javadoc注解中亡脑,每個(gè)類都必須有注解。
/*** Copyright (C), 2019-2020, Jann balabala...** 類的介紹:這是一個(gè)用來做什么事情的類邀跃,有哪些功能霉咨,用到的技術(shù).....** @author 類創(chuàng)建者姓名 保持對(duì)齊* @date 創(chuàng)建日期 保持對(duì)齊* @version 版本號(hào) 保持對(duì)齊*/
c. 屬性注解
在每個(gè)屬性前面必須加上屬性注釋,通常有一下兩種形式拍屑,至于怎么選擇躯护,你高興就好,不過一個(gè)項(xiàng)目中要保持統(tǒng)一丽涩。
/** 提示信息 */private String userName;/** * 密碼 */private String password;
d. 方法注釋
在每個(gè)方法前面必須加上方法注釋棺滞,對(duì)于方法中的每個(gè)參數(shù),以及返回值都要有說明矢渊。
/** * 方法的詳細(xì)說明继准,能干嘛,怎么實(shí)現(xiàn)的矮男,注意事項(xiàng)... * * @param xxx 參數(shù)1的使用說明移必, 能否為null * @return 返回結(jié)果的說明, 不同情況下會(huì)返回怎樣的結(jié)果 * @throws 異常類型 注明從此類方法中拋出異常的說明 */
e. 構(gòu)造方法注釋
在每個(gè)構(gòu)造方法前面必須加上注釋毡鉴,注釋模板如下:
/** * 構(gòu)造方法的詳細(xì)說明 * * @param xxx 參數(shù)1的使用說明崔泵, 能否為null * @throws 異常類型 注明從此類方法中拋出異常的說明 */
而簡單注解往往是需要工程師字節(jié)定義,在使用注解時(shí)應(yīng)該注意一下幾點(diǎn):
- 枚舉類的各個(gè)屬性值都要使用注解猪瞬,枚舉可以理解為是常量憎瘸,通常不會(huì)發(fā)生改變,通常會(huì)被在多個(gè)地方引用陈瘦,對(duì)枚舉的修改和添加屬性通常會(huì)帶來很大的影響幌甘。
- 保持排版整潔,不要使用行尾注釋痊项;雙斜杠和星號(hào)之后要用1個(gè)空格分隔锅风。
int id = 1;// 反例:不要使用行尾注釋//反例:換行符與注釋之間沒有縮進(jìn)int age = 18;// 正例:姓名String name;/** * 1\. 多行注釋 * * 2\. 對(duì)于不同的邏輯說明,可以用空行分隔 */
總結(jié)
無論是命名和注解鞍泉,他們的目的都是為了讓代碼和工程師進(jìn)行對(duì)話皱埠,增強(qiáng)代碼的可讀性,可維護(hù)性咖驮。優(yōu)秀的代碼往往能夠見名知意边器,注解往往是對(duì)命名的補(bǔ)充和完善训枢。命名太南了!