一般來說痴颊,代碼規(guī)范是一個企業(yè)每個開發(fā)人員都必須遵循的規(guī)定,發(fā)布前會有統(tǒng)一代碼自動檢測屡贺,違反任何一條都不允許發(fā)布蠢棱。個人認為,開發(fā)人員除了要遵循這些硬性規(guī)定甩栈,平常也應該要有良好的偏軟性的代碼習慣泻仙,就像生活中除了法律還有大家都崇尚的道德一樣。兩者的出發(fā)點都是為了確保更高的代碼質量量没,只是有些規(guī)定不好自動化或者沒有被考慮到玉转,就只能作為一個良好的代碼習慣存在著。Code Review階段是審查代碼習慣的一個好時機殴蹄。下面羅列一下我自己在工作中總結的十幾條比較好的代碼習慣:
不涉及數(shù)據(jù)庫查詢的參數(shù)校驗或參數(shù)修正究抓,應該停留在controller層猾担,只有涉及數(shù)據(jù)庫查詢的校驗才可以放到service層(比如數(shù)據(jù)查重)。這樣可以保持service層邏輯的整潔刺下,避免被一大堆的校驗代碼污染可讀性绑嘹,同時清晰的代碼責任分離有助于更快定位問題代碼的位置。校驗建議最好都使用注解或自定義注解橘茉。不過目前hibernate-validator的自定義注解寫法實在丑陋工腋,不易讀不易維護不易復用,還不如直接在dto上直接寫個validate的方法來的簡單直接畅卓。
對entity的處理應該在entity中封裝對應的構造方法或create方法或edit方法來處理擅腰,不應一大坨代碼放在service。有些杠精可能會說應該避免充血模型翁潘,貧血模型才是正道惕鼓,額,概念我不是特別懂唐础,反正這些模型概念被創(chuàng)造出來就是為了更整潔可維護的代碼,過分強調(diào)某個模型多少有點過度設計的味道矾飞,這里只會把entity的創(chuàng)建編輯等只針對當前entity的操作封裝在里面一膨,不涉及其他邏輯,方法也不會定義很多洒沦,足夠簡單豹绪,何樂而不為。
一個復雜方法的實現(xiàn)申眼,看起來應該像一個大綱一樣瞒津,第一步做什么,第二步做什么括尸,第三步做什么巷蚪,每一步基本應該只需要一兩行代碼完成,復雜方法(尤其是service層的方法)中不應該有每一步的具體邏輯濒翻,具體邏輯應該另外封裝方法屁柏,如果另外封裝的方法也較為復雜,應該再進一步列大綱分步封裝方法有送。封裝方法時淌喻,要考慮好方法應該放在什么位置,過多的在一個類中封裝private方法也容易導致代碼顯得雜亂無章雀摘,這時候可能單獨針對較為復雜的業(yè)務邏輯相關的方法抽離到一個輔助類中裸删。
底層方法簽名要盡可能通用,比如service阵赠,dao層的方法要盡量考慮復用涯塔,避免使用DTO復雜類型作為參數(shù)肌稻,避免使用Result這種接口規(guī)范響應參數(shù)或者VO作為返回值,避免使用Map/JsonObject這種字段不清晰的結構作為參數(shù)或返回值伤塌。當然個別情況無法避免灯萍,比如創(chuàng)建,編輯時參數(shù)過多每聪,只能使用DTO旦棉,又比如service的返回是分頁的結果,只能用Page包裝等药薯。但對于比如queryById等這種入?yún)⒑统鰠⒖梢远x成簡單形式的應該保留簡單形式绑洛,在controller層再進行Result的包裝,盡管這個方法暫時沒有被復用童本,也應該遵循這個原則真屯。
盡管業(yè)務上規(guī)定有些情況可以寫死,也應該考慮寫死的位置應該盡可能保證影響最小化穷娱。比如實現(xiàn)通過頁面創(chuàng)建數(shù)據(jù)庫的功能是绑蔫,業(yè)務規(guī)定建索引只能所以其他表的id,在對索引的數(shù)據(jù)建模時泵额,應考慮按照通俗理解去定義索引的數(shù)據(jù)模型配深,在校驗層去限制只能索引id字段,這樣如果將來有變嫁盲,也只需要放開校驗即可篓叶,而且按照通俗理解的去定義,別人一看就能看明白羞秤。當然也要衡量這么做的工作量缸托,如果額外工作量過大就沒必要了。
善用通用工具類的封裝去避免業(yè)務代碼的啰唆瘾蛋,除了常規(guī)的各種StringUtils, CollectionUtils俐镐,在業(yè)務代碼實現(xiàn)時也可考慮自行封裝。比如分布式鎖的try catch finally塊就很啰唆哺哼,可以考慮使用Runnable把try catch finally搬到通用方法中京革,調(diào)用時只需傳遞Runnable參數(shù)即可。
針對每個提供的http接口幸斥,要清晰地定義接口的入?yún)TO和出參VO匹摇,維護好swagger,盡量避免使用Map/JsonObject甲葬,不應直接使用entity廊勃,也不要輕易復用DTO/VO,除非是完全一樣的參數(shù)才可考慮復用,否則都很容易混亂坡垫,后期很難維護梭灿。
盡量避免在當前entityService寫其他entity的數(shù)據(jù)庫邏輯,其他entity的邏輯應該寫到它所屬的service中冰悠,通過注入該service類進行調(diào)用堡妒。
復雜邏輯一定要多寫注釋,review代碼發(fā)現(xiàn)自己都看不懂時一定要及時補上注釋溉卓。
單元測試皮迟,應該避免依賴數(shù)據(jù)庫已存在的數(shù)據(jù),以及跑完之后殘留臟數(shù)據(jù)的情況桑寨。具體可以考慮封裝相應的工具類伏尼,使用@Before在測試方法之前插入所需數(shù)據(jù),通過@After或者spring生命周期的destroy方法刪掉過程中創(chuàng)建的數(shù)據(jù)尉尾。比較好一點的方案是使用mybatis攔截器來收集過程中插入的數(shù)據(jù)以便刪除爆阶。另外,插入的數(shù)據(jù)可以作特殊處理沙咏,比如對于自動生成的id加上某個固定的前綴辨图,萬一數(shù)據(jù)沒有成功清理時可以比較輕易地手動清理。
寫代碼時盡可能以最直觀的方式去實現(xiàn)肢藐,避免因為遇到困難而選擇一些曲折的方案徒役,這樣會導致代碼可讀性差,維護難度大窖壕。遇到問題不要繞行,要弄清楚為什么會有問題杉女,能否解決瞻讽,不能解決的情況下再考慮使用其他方案,并做好注釋熏挎。
遇到某些難以定位的bug時速勇,不要亂,要善用排除法坎拐,比如先將代碼恢復到正常的時間節(jié)點烦磁,然后一點一點的增加后來修改的邏輯,逐步定位到出問題的大概位置(比如WebConfigurer問題定位)哼勇。
雖然通常代碼規(guī)范限制嵌套不能超過3層都伪,而且有些大括號塊還不算嵌套,比如try catch积担,但我個人覺得陨晶,3層就已經(jīng)很丑了,應該盡量確保在一個方法內(nèi)最多2層大括號嵌套帝璧,嵌套的代碼可讀性實在很差先誉,能封裝方法就封裝方法湿刽。
軟性規(guī)范,見仁見智褐耳,歡迎談論诈闺。