說起代碼品質,腦子裡會冒出很多詞,命名規範、格式規範、日志規範、單元測試覆寫率... 但我覺得,代碼品質總結起來就兩個:好看和好用。 好看是指代碼可讀性好,容易了解、容易維護,别人接手了不罵你;好用則指代碼健壯,不容易出錯,機器跑着不罵你。即使出錯,也容易定位,容易止損和恢複。為何需要提高代碼品質?
以下是我認為的幾點:
提升代碼的可維護性,降低新人接手的成本
促進交流,促進知識共享,做好backup
促進風格一緻,降低團隊間應用流轉的難度
建設寫好代碼、做好設計的團隊氛圍
但有一點需要說明,我認為寫代碼本身是一個創造過程,能讓人享受其中,如果有太多的條條框框限制,寫代碼就失去了創造的樂趣,是以,這裡為代碼品質建設立一個原則:
隻提供建議,不強制遵循
鼓勵創造性的編碼
鼓勵藝術性的編碼
有兩種途徑:
第一種途徑:先有好的設計--->然後用優秀的編碼去實作--->再把優秀的編碼風格延續下去
第二種途徑:從糟糕的代碼開始--->不斷去重構,向優秀的設計方案和代碼風格不斷逼近--->再延續下去
首先得知道什麼是好的代碼,這就要有标準,那就是我們常常看到的各種各樣的規範,但我覺得要有幾個簡單的原則,太多了,記不住,有幾條原則簡單的原則,可以時不時拿來判斷,目前做得對不對。
然後就是去實踐規範,這裡需要一些技巧、一些工具,來幫助我們更好地遵循規範。
接着是度量,看我們對規範實踐的效果,這就是我們常說也常做的Code Review,但Code Review也需要遵循一定的規範,應用一定的技巧。
度量之後是改進,CR結果要及時跟進,這是最重要一環,否則CR就沒有實際意義。
總結不可少,複盤是一種很有用的工具,CR也需要複盤,總結CR流程、過程等方面好的和不好的地方,更新規範和checklist。
接下來我們分别聊一聊各個步驟。
從上邊高品質代碼的誕生途徑我們可以看出,設計也是很重要的一環,是以我們的規範包括設計規範和編碼規範,結合我們的生産實際,這裡加上安全生産的規範,是以規範有3部分:設計、編碼、安全生産。
設計: 先有優秀的方案
設計推薦多用圖表達,圖比文字有更直覺的傳達能力:
首先是業務流程圖,它能快速建構起我們對業務的認知,帶着對業務的了解再來看代碼,事半功倍。
然後是用例圖,清晰地表達出我們系統的職責、邊界、服務對象,結合業務流程圖,能快速建構起我們對系統職責的認知。
接着是架構圖,從我們日常的設計需求來看,架構圖是需要的。好的架構圖能快速給人搭建起了解的架構,再來看系統的細節部分,就很好了解。架構圖推薦 C4 規範,它是我目前接觸的表達最清晰的架構圖規範。
接着再用時序圖、狀态圖、ER圖等把關鍵和複雜部分的設計表達出來。
但日常我們的需求有大有小,方案也不需要都遵循統一的範本,為了設計而設計,就徒增加工作量了。以按需為第一原則,能把要做啥,怎麼做的表達清楚即可。這裡按場景推薦各個圖的使用場景:
建立應用/對原有應用進行重大修改/複雜項目
業務流程圖(交代業務背景)
C4的系統上下文、容器、元件這3張圖
用例圖:有多個外部參與者
類圖:關鍵模型超過5個
狀态圖:對象狀态超過3個
時序圖:關鍵流程或複雜鍊路的參與對象超過3個
ER圖:涉及資料庫變更(包含資料表結構文檔)
一般項目/重大日常
業務流程圖
時序圖(複雜功能、關鍵流程)
日常
按需
編碼最重要的是可讀,控制複雜度,做到自解釋,能讓人像讀自然語言一樣讀自己的代碼,這是最高境界,也是神仙境界。然後是可維護性和可變更性,能快速、安全地修改代碼是目标。最後是對優雅實作的要求,卓越的代碼會讓人拍着大腿叫好,這個不稀奇,我們亂糟糟的代碼裡也偶爾會有閃光的片段。
編碼最高原則:
可讀性
控制複雜度
self-document
可維護性
優雅
合理的代碼分層,能控制各層的複雜度,以分層的思路去設計,也能提高代碼的複用性。對于分層,我認為熟悉的就是好的,能滿足工作中的大部分情況就好,這裡不談六邊形架構、清晰架構、DODAF等概念,自己駕馭不了,還不能拿出來吹。我推薦DDD最基礎的4層分層架構,如下:
這裡舉個我實際項目中用到的例子:
上述項目結構中,因為是導購項目,view相當于使用者界面層,application是應用層,domain是領域層,infrastructure是基礎設施層。
再對包的劃分說明一下:
領域對象、值對象、DTO、Service等定義都放在子域的包下,不要有大而全的entity、service、impl等包(這裡的子域是一個内聚的邏輯概念,對應的是領域設計裡的子域,如上例中的item在我們的導購裡就是商品這個子域)
常量定義盡量跟着相關的類走,作為類的靜态字段,不要有大而全的Constant類(Switch相關的除外,但也要按職責盡量拆分開關類)
代碼規範就推薦阿裡經濟體開發規約,很全面,也是阿裡同學的基本要求。代碼規範就推薦「阿裡經濟體開發規約」,很全面,也是阿裡同學的基本要求,開源版本:阿裡巴巴java開發手冊 https://github.com/alibaba/p3c
結合自己的經驗,重點說幾點:
命名
命名不用泛稱(反例:processData)
盡量用完整的單詞描述清楚作用和意圖,不要怕字多
對象字尾領域對象不帶字尾DTO:RPC接口提供的對象以作為VO:跟前端互動的對象PO:跟資料庫直接互動的對象
日志
所有背景都要有記錄檔、資料變更日志
日志要配置異步寫盤
線上僅保留WARN和ERROR級别日志
所有日志都要有traceId
異常日志要有堆棧、入參、能說清楚是什麼錯誤的資訊(可以出統一元件)
列印日志時,禁止直接用JSON工具将對象轉換成String
異常
怎麼抛:盡量使用非受檢異常,提高代碼可讀性
怎麼處理:統一異常用切面處理,或依賴SpringMvc的ControllerAdvice統一處理
異常catch範圍盡量小,厘清穩定代碼和非穩定代碼
禁止直接吞掉異常
時刻警惕NPE,多用Optional處理
注釋
注釋隻為了說明為什麼這麼做,不用來說明是在做什麼
面向對象
遵循原則:SRP/OCP/LSP/ISP/DIP
盡量隻暴露行為,不暴露資料
慎用繼承,優先使用組合方式
其它規範
方法行數保持在一屏之内(30行以内)
代碼送出commit message一定要講清楚做了啥控制每次送出的代碼量(一個功能一送出)
參數盡量用不可變對象(不對入參做修改,保持明确的入參和出參)盡量不用隐式入參(ThreadLocal)
資料結構無随機讀取時,用LinkedList替代ArrayList
風格做好分層,同層用統一的風格(設計/編碼)
安全生産還沒有系統總結過,結合自己做穩定性的工作經驗提幾點,後邊跟負責安全生産的同學多學習學習,再來更新:
防資損
要有資損評估/監控
易恢複
任何新功能上線都要有灰階能力
監控/報警
兜底設計/監控
性能監控
異常監控
低容忍錯誤要報警
關鍵名額要監控(業務/技術)
減少不必要的報警
降級/限流
識别出弱依賴,保證弱依賴可降級
識别出可限流的依賴方,做好監控和限流配置
給一些原則和技巧建議,幫忙落地規範。
設計
圖都不是必須的,隻要能講明白是怎麼做的,為什麼這麼做
使用Aone-Idea,它已經內建了PMD/FindBugs/CheckStyle功能,給開發的同學點個暫,超牛逼。開源版本:Alibaba Java Coding Guidelines alibaba https://plugins.jetbrains.com/plugin/10046-alibaba-java-coding-guidelines
使用lombok,保持代碼的簡潔性
不斷重構,且遵循以下原則: DRY/YAGNI/Rule Of Three/KISS/POLA每次需求都是重構契機反問自己,能不能在[可讀性/易維護性]做得更好
使代碼讀起來像自然語言
功能性代碼和非功能性代碼分離
這得跟着公司和部門規範來,學習學習再來補充。
Review時機
項目提測後第一時間:不要在項目上線的前夜review,來不及改,review結果容易擱置,浪費參與人的青春
Review方式
小子產品:随時/Aone代碼評審/@backup同學
項目代碼:面對面投屏/Aone代碼評審 + IDE show/項目組+重點關注同學
Review内容
關注代碼的設計是如何落地需求的
總體流程
關鍵設計
重點功能
Review前提
代碼是編譯通過的
開啟Aone-Idea的實時檢測
Checklist
規範性
可維護性(高内聚低耦合、面向對象原則、實作複雜性等)
可變更性(擴充性等)
安全性/健壯性輸入檢查異常處理邊界檢查
性能依賴合理性
有運作時風險的問題必須上線前完成改動
其它問題盡量上線前完成修改,如未修改則要加todo,指定人和時間來修改
用工具來統計和提示CR結果改進情況
定期回顧和總結(周會環節)
更新checklist和代碼規範
發現好的代碼和設計,定期展示,給與獎勵